From 92e8e7555e6e0b468c51bd30ebf1ee2045a6877f Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Fri, 1 Dec 2023 21:17:46 +0530 Subject: [PATCH 01/22] feat: add timestamp based contract functionality --- .env.example | 26 +- .github/workflows/ci.yaml | 35 + CHANGELOG.md | 50 + README.md | 10 +- contracts/BaseJumpRateModelV2.sol | 200 - contracts/JumpRateModelV2.sol | 206 +- contracts/Lens/PoolLens.sol | 62 +- contracts/Rewards/RewardsDistributor.sol | 330 +- contracts/Shortfall/Shortfall.sol | 115 +- contracts/TimeManager.sol | 60 + contracts/VToken.sol | 107 +- contracts/VTokenInterfaces.sol | 2 +- contracts/WhitePaperInterestRateModel.sol | 36 +- contracts/lib/constants.sol | 4 +- contracts/test/UpgradedVToken.sol | 11 + contracts/test/VTokenHarness.sol | 19 +- deploy/003-price-oracle-configure-feeds.ts | 2 +- deploy/007-deploy-pool-lens.ts | 6 +- deploy/009-deploy-vtokens.ts | 26 +- deploy/010-deploy-reward-distributors.ts | 9 +- deploy/011-initial-liquidity.ts | 17 +- deploy/013-vip-based-config.ts | 41 +- deploy/014-riskfund-protocolshare.ts | 5 +- deploy/015-transfer-funds-ownership.ts | 47 + deployments/bscmainnet.json | 13829 +- ...slope2000bps_jump30000bps_kink4500bps.json | 497 + .../ProtocolShareReserve_Implementation.json | 711 - .../bscmainnet/RewardsDistributor_DeFi_2.json | 1270 + ...n => RewardsDistributor_DeFi_2_Proxy.json} | 98 +- .../bscmainnet/VToken_vPLANET_DeFi.json | 246 + deployments/bsctestnet.json | 152402 ++++++++++++++- ...slope2000bps_jump30000bps_kink4500bps.json | 497 + deployments/bsctestnet/MockPLANET.json | 450 + .../ProtocolShareReserve_Implementation.json | 711 - .../bsctestnet/RewardsDistributor_DeFi_2.json | 1270 + ...n => RewardsDistributor_DeFi_2_Proxy.json} | 522 +- .../bsctestnet/VToken_vPLANET_DeFi.json | 246 + .../82cd33260a9b17bbce6d70381b9dc2d8.json | 300 + deployments/ethereum.json | 5 + deployments/sepolia.json | 17017 ++ deployments/sepolia/.chainId | 1 + deployments/sepolia/ComptrollerBeacon.json | 206 + deployments/sepolia/ComptrollerImpl.json | 2744 + deployments/sepolia/Comptroller_Core.json | 176 + deployments/sepolia/Comptroller_Curve.json | 176 + .../sepolia/Comptroller_Stablecoins.json | 176 + deployments/sepolia/DefaultProxyAdmin.json | 257 + ...s_slope450bps_jump8000bps_kink8000bps.json | 519 + ...s_slope500bps_jump8000bps_kink7500bps.json | 519 + ...s_slope700bps_jump8000bps_kink8000bps.json | 519 + ...slope1500bps_jump30000bps_kink4500bps.json | 519 + ...slope2000bps_jump30000bps_kink4500bps.json | 519 + deployments/sepolia/MockCRV.json | 450 + deployments/sepolia/MockUSDC.json | 450 + deployments/sepolia/MockUSDT.json | 450 + deployments/sepolia/MockWBTC.json | 450 + deployments/sepolia/MockWETH.json | 450 + deployments/sepolia/MockcrvUSD.json | 450 + deployments/sepolia/PoolLens.json | 1274 + .../PoolRegistry.json} | 598 +- .../sepolia/PoolRegistry_Implementation.json | 1189 + .../PoolRegistry_Proxy.json} | 92 +- .../sepolia/RewardsDistributorImpl.json | 1545 + deployments/sepolia/VTokenBeacon.json | 206 + deployments/sepolia/VTokenImpl.json | 3021 + deployments/sepolia/VToken_vCRV_Core.json | 246 + deployments/sepolia/VToken_vCRV_Curve.json | 246 + deployments/sepolia/VToken_vUSDC_Core.json | 246 + .../sepolia/VToken_vUSDC_Stablecoins.json | 246 + deployments/sepolia/VToken_vUSDT_Core.json | 246 + .../sepolia/VToken_vUSDT_Stablecoins.json | 246 + deployments/sepolia/VToken_vWBTC_Core.json | 246 + deployments/sepolia/VToken_vWETH_Core.json | 246 + deployments/sepolia/VToken_vcrvUSD_Core.json | 246 + deployments/sepolia/VToken_vcrvUSD_Curve.json | 246 + .../sepolia/VToken_vcrvUSD_Stablecoins.json | 246 + .../0e89febeebc7444140de8e67c9067d2c.json | 78 + .../2bf9f23321dda7abe5f536a221df7bce.json | 285 + .../8249036c2fd27f6f9b40677e2c950aaf.json | 285 + .../cdedc94c3b6a3494ec3d604a8209c227.json | 300 + hardhat.config.ts | 62 +- helpers/deploymentConfig.ts | 868 +- helpers/deploymentUtils.ts | 17 +- package.json | 10 +- tests/hardhat/Fork/RewardsForkTest.ts | 4 +- tests/hardhat/Fork/RiskFund.ts | 2 +- tests/hardhat/Fork/RiskFundSwap.ts | 12 +- tests/hardhat/Fork/Shortfall.ts | 2 +- tests/hardhat/Fork/borrowAndRepayTest.ts | 4 +- tests/hardhat/Fork/liquidation.ts | 2 +- tests/hardhat/Fork/reduceReservesTest.ts | 4 +- tests/hardhat/Fork/supply.ts | 2 +- tests/hardhat/Fork/utils.ts | 2 +- tests/hardhat/JumpRateModelV2.ts | 222 +- tests/hardhat/Lens/PoolLens.ts | 762 +- tests/hardhat/Lens/RewardsSummary.ts | 331 +- tests/hardhat/Rewards.ts | 531 +- tests/hardhat/Shortfall.ts | 1203 +- tests/hardhat/Tokens/accrueInterestTest.ts | 211 +- tests/hardhat/UpgradedVToken.ts | 181 +- tests/hardhat/WhitePaperInterestRateModel.ts | 113 +- tests/hardhat/util/TokenTestHelpers.ts | 19 +- tests/hardhat/util/descriptionHelpers.ts | 6 + tests/integration/index.ts | 20 +- yarn.lock | 71 +- 105 files changed, 196972 insertions(+), 19796 deletions(-) delete mode 100644 contracts/BaseJumpRateModelV2.sol create mode 100644 contracts/TimeManager.sol create mode 100644 deploy/015-transfer-funds-ownership.ts create mode 100644 deployments/bscmainnet/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json delete mode 100644 deployments/bscmainnet/ProtocolShareReserve_Implementation.json create mode 100644 deployments/bscmainnet/RewardsDistributor_DeFi_2.json rename deployments/bscmainnet/{ProtocolShareReserve_Proxy.json => RewardsDistributor_DeFi_2_Proxy.json} (93%) create mode 100644 deployments/bscmainnet/VToken_vPLANET_DeFi.json create mode 100644 deployments/bsctestnet/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json create mode 100644 deployments/bsctestnet/MockPLANET.json delete mode 100644 deployments/bsctestnet/ProtocolShareReserve_Implementation.json create mode 100644 deployments/bsctestnet/RewardsDistributor_DeFi_2.json rename deployments/bsctestnet/{ProtocolShareReserve.json => RewardsDistributor_DeFi_2_Proxy.json} (84%) create mode 100644 deployments/bsctestnet/VToken_vPLANET_DeFi.json create mode 100644 deployments/bsctestnet/solcInputs/82cd33260a9b17bbce6d70381b9dc2d8.json create mode 100644 deployments/ethereum.json create mode 100644 deployments/sepolia.json create mode 100644 deployments/sepolia/.chainId create mode 100644 deployments/sepolia/ComptrollerBeacon.json create mode 100644 deployments/sepolia/ComptrollerImpl.json create mode 100644 deployments/sepolia/Comptroller_Core.json create mode 100644 deployments/sepolia/Comptroller_Curve.json create mode 100644 deployments/sepolia/Comptroller_Stablecoins.json create mode 100644 deployments/sepolia/DefaultProxyAdmin.json create mode 100644 deployments/sepolia/JumpRateModelV2_base0bps_slope450bps_jump8000bps_kink8000bps.json create mode 100644 deployments/sepolia/JumpRateModelV2_base0bps_slope500bps_jump8000bps_kink7500bps.json create mode 100644 deployments/sepolia/JumpRateModelV2_base0bps_slope700bps_jump8000bps_kink8000bps.json create mode 100644 deployments/sepolia/JumpRateModelV2_base200bps_slope1500bps_jump30000bps_kink4500bps.json create mode 100644 deployments/sepolia/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json create mode 100644 deployments/sepolia/MockCRV.json create mode 100644 deployments/sepolia/MockUSDC.json create mode 100644 deployments/sepolia/MockUSDT.json create mode 100644 deployments/sepolia/MockWBTC.json create mode 100644 deployments/sepolia/MockWETH.json create mode 100644 deployments/sepolia/MockcrvUSD.json create mode 100644 deployments/sepolia/PoolLens.json rename deployments/{bscmainnet/ProtocolShareReserve.json => sepolia/PoolRegistry.json} (84%) create mode 100644 deployments/sepolia/PoolRegistry_Implementation.json rename deployments/{bsctestnet/ProtocolShareReserve_Proxy.json => sepolia/PoolRegistry_Proxy.json} (94%) create mode 100644 deployments/sepolia/RewardsDistributorImpl.json create mode 100644 deployments/sepolia/VTokenBeacon.json create mode 100644 deployments/sepolia/VTokenImpl.json create mode 100644 deployments/sepolia/VToken_vCRV_Core.json create mode 100644 deployments/sepolia/VToken_vCRV_Curve.json create mode 100644 deployments/sepolia/VToken_vUSDC_Core.json create mode 100644 deployments/sepolia/VToken_vUSDC_Stablecoins.json create mode 100644 deployments/sepolia/VToken_vUSDT_Core.json create mode 100644 deployments/sepolia/VToken_vUSDT_Stablecoins.json create mode 100644 deployments/sepolia/VToken_vWBTC_Core.json create mode 100644 deployments/sepolia/VToken_vWETH_Core.json create mode 100644 deployments/sepolia/VToken_vcrvUSD_Core.json create mode 100644 deployments/sepolia/VToken_vcrvUSD_Curve.json create mode 100644 deployments/sepolia/VToken_vcrvUSD_Stablecoins.json create mode 100644 deployments/sepolia/solcInputs/0e89febeebc7444140de8e67c9067d2c.json create mode 100644 deployments/sepolia/solcInputs/2bf9f23321dda7abe5f536a221df7bce.json create mode 100644 deployments/sepolia/solcInputs/8249036c2fd27f6f9b40677e2c950aaf.json create mode 100644 deployments/sepolia/solcInputs/cdedc94c3b6a3494ec3d604a8209c227.json create mode 100644 tests/hardhat/util/descriptionHelpers.ts diff --git a/.env.example b/.env.example index a54f694bf..6b9d97696 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,22 @@ -MNEMONIC= -ETHERSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1 -FORK_MAINNET=false -QUICK_NODE_KEY=ABC123ABC123ABC123ABC123ABC123ABC1 +# true or false +FORK=false +FORKED_NETWORK=bscmainnet + +# Replace with your deployer's private key +DEPLOYER_PRIVATE_KEY= + +## Archive nodes - Replace with your actual keys and uncomment the line you need +## ARCHIVE_NODE_bsctestnet=https://bsc-testnet.nodereal.io/v1/ +## ARCHIVE_NODE_bscmainnet=https://bsc-mainnet.nodereal.io/v1/ +## ARCHIVE_NODE_sepolia=https://ethereum-sepolia.blockpi.network/v1/rpc/public +## ARCHIVE_NODE_ethereum=https://eth-mainnet.nodereal.io/v1/ + +# Uncomment the lines below if you want to deploy on mainnet using Frame Wallet +#ARCHIVE_NODE_ethereum=http://127.0.0.1:1248 +#ARCHIVE_NODE_bscmainnet=http://127.0.0.1:1248 + +# Replace with your Etherscan API key +ETHERSCAN_API_KEY= + +# Set to true or false to control gas reporting +REPORT_GAS= diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 387c1f5f5..47548dc01 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -89,3 +89,38 @@ jobs: - name: Verify deployments work run: yarn hardhat deploy + + export-deployments: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Check out code + uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + token: ${{ secrets.VENUS_TOOLS_TOKEN }} + + - name: Setup Node.js environment + uses: actions/setup-node@v2 + with: + node-version: 18 + cache: "yarn" + + - name: Install dependencies + # Hack to get around failing "ethereumjs-abi The remote archive doesn't match the expected checksum" error + run: YARN_CHECKSUM_BEHAVIOR=update yarn + + - name: Export deployments + run: | + yarn hardhat export --network bsctestnet --export ./deployments/bsctestnet.json + yarn hardhat export --network bscmainnet --export ./deployments/bscmainnet.json + yarn hardhat export --network sepolia --export ./deployments/sepolia.json + yarn hardhat export --network ethereum --export ./deployments/ethereum.json + yarn prettier + + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "feat: updating deployment files" + file_pattern: "deployments/*.json" diff --git a/CHANGELOG.md b/CHANGELOG.md index c23d4404f..3b5fb7012 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,53 @@ +## [2.3.0-dev.3](https://github.com/VenusProtocol/isolated-pools/compare/v2.3.0-dev.2...v2.3.0-dev.3) (2023-11-30) + + +### Features + +* updating deployment files ([f1e3083](https://github.com/VenusProtocol/isolated-pools/commit/f1e3083c56a6bca47752928016fb26517cb9c880)) +* updating deployment files ([d2b7cdb](https://github.com/VenusProtocol/isolated-pools/commit/d2b7cdb02d284e0582b5edef3e36df7332e12143)) +* updating deployment files ([b957327](https://github.com/VenusProtocol/isolated-pools/commit/b957327247f2d5d6c50591fa8dc31a0d97e60a9b)) +* updating deployment files ([386581f](https://github.com/VenusProtocol/isolated-pools/commit/386581fd775994ba6bf469e99c0c0f31c71654a7)) + + +### Bug Fixes + +* bump protocol package version ([7bad19c](https://github.com/VenusProtocol/isolated-pools/commit/7bad19ceffacebda66270216d74b1a786d49e594)) +* compilation error ([b78e110](https://github.com/VenusProtocol/isolated-pools/commit/b78e1100557ce5723c2302ca28265165a24a0c55)) +* config of usdt_core ([f63346a](https://github.com/VenusProtocol/isolated-pools/commit/f63346a58644fbb1bc3f51edbfbbdbead25d40f4)) +* delete unused contract for this repo ([e3f1625](https://github.com/VenusProtocol/isolated-pools/commit/e3f1625654a24a2e71a8cddff3924d98c8f44198)) +* deployment scripts for local deployment and update oracle package version fixing oracle deployments locally ([efdf4c0](https://github.com/VenusProtocol/isolated-pools/commit/efdf4c0584b62020eea3c4f3f4b92877e44b9414)) +* format code ([bfaacdd](https://github.com/VenusProtocol/isolated-pools/commit/bfaacdded66adec803d9be0877733610055c9d21)) +* hardhat config file ([0939e0a](https://github.com/VenusProtocol/isolated-pools/commit/0939e0af70db867d8350af8f8fc586ed6dd33409)) +* lint and preconfiguredAddress decaration of Vtreasury wrong reference ([8469906](https://github.com/VenusProtocol/isolated-pools/commit/8469906743f1b9b7e2ea527fe71c7d25236d35ad)) +* riskfund deploy script fix (wrong resolution of merge conflict) ([4244f64](https://github.com/VenusProtocol/isolated-pools/commit/4244f649deb9400df55419634f0baef1874b0390)) +* tests ([b8c14c0](https://github.com/VenusProtocol/isolated-pools/commit/b8c14c0fd912b7d466fa71ef86a6018734f3b4f4)) +* update venus-protocol version ([46e1327](https://github.com/VenusProtocol/isolated-pools/commit/46e132714bab723863fd13baeec23c01ceab8a00)) +* yarn build ([8234296](https://github.com/VenusProtocol/isolated-pools/commit/823429638d7a6d3b237a7ec6cf011865ae81c878)) + +## [2.3.0-dev.2](https://github.com/VenusProtocol/isolated-pools/compare/v2.3.0-dev.1...v2.3.0-dev.2) (2023-11-17) + + +### Features + +* add github job to export and commit deployment by network ([33f92fc](https://github.com/VenusProtocol/isolated-pools/commit/33f92fc23ff11cbd75138a18b31bc6ffb262281a)) +* support exporting sepolia and ethereum deployments ([db0ef9c](https://github.com/VenusProtocol/isolated-pools/commit/db0ef9cd1c7df3ed05174203b8a4b0f19075b749)) +* updating deployment files ([4950a26](https://github.com/VenusProtocol/isolated-pools/commit/4950a269f7c616e22502eebbd955bdb3ceb4e2fe)) + +## [2.3.0-dev.1](https://github.com/VenusProtocol/isolated-pools/compare/v2.2.1-dev.1...v2.3.0-dev.1) (2023-11-13) + + +### Features + +* add PLANET market deployments ([fa21a3d](https://github.com/VenusProtocol/isolated-pools/commit/fa21a3d769046c7cc67de918e1b6b505db5f5141)) +* export PLANET market deployment ([fc1c874](https://github.com/VenusProtocol/isolated-pools/commit/fc1c874f7ec28910d63ae77a8c3347cf00bb269b)) +* update script to use psr addresses from protocol-reserve package ([a63cdd9](https://github.com/VenusProtocol/isolated-pools/commit/a63cdd929329c8844207ac9e6717d8d8332c885c)) + + +### Bug Fixes + +* reduce reserves block delta in deployment configs ([9def1eb](https://github.com/VenusProtocol/isolated-pools/commit/9def1eb75d047c7f3bb043b938dc84c7330631fd)) +* whitespaces ([7ea26e4](https://github.com/VenusProtocol/isolated-pools/commit/7ea26e405ebe2c584fa4a3ec74a27bf047e20883)) + ## [2.2.1-dev.1](https://github.com/VenusProtocol/isolated-pools/compare/v2.2.0...v2.2.1-dev.1) (2023-11-03) diff --git a/README.md b/README.md index 2ae44fe6b..e90fd52f0 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ REPORT_GAS=true npx hardhat test ``` -- To run fork tests add FORK_MAINNET=true and QUICK_NODE_KEY in the .env file. +- To run fork tests add FORK=true, FORKED_NETWORK and one ARCHIVE_NODE var in the .env file. ## Deployment @@ -127,6 +127,14 @@ npx hardhat deploy - In the deployment scripts you have added `tags` for example: - `func.tags = ["MockTokens"];` - Once this is done, adding `--tags ",..."` to the deployment command will execute only the scripts containing the tags. +### Deployed Contracts + +Deployed contract abis and addresses are exported in the `deployments` directory. To create a summary export of all contracts deployed to a network run + +``` +$ yarn hardhat export --network --export ./deployments/.json +``` + ## Source Code Verification In order to verify the source code of already deployed contracts, run: diff --git a/contracts/BaseJumpRateModelV2.sol b/contracts/BaseJumpRateModelV2.sol deleted file mode 100644 index ce8693329..000000000 --- a/contracts/BaseJumpRateModelV2.sol +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -pragma solidity 0.8.13; - -import { IAccessControlManagerV8 } from "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol"; - -import { InterestRateModel } from "./InterestRateModel.sol"; -import { BLOCKS_PER_YEAR, EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; - -/** - * @title Logic for Compound's JumpRateModel Contract V2. - * @author Compound (modified by Dharma Labs, Arr00 and Venus) - * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached. - * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters. - */ -abstract contract BaseJumpRateModelV2 is InterestRateModel { - /** - * @notice The address of the AccessControlManager contract - */ - IAccessControlManagerV8 public accessControlManager; - - /** - * @notice The multiplier of utilization rate that gives the slope of the interest rate - */ - uint256 public multiplierPerBlock; - - /** - * @notice The base interest rate which is the y-intercept when utilization rate is 0 - */ - uint256 public baseRatePerBlock; - - /** - * @notice The multiplier per block after hitting a specified utilization point - */ - uint256 public jumpMultiplierPerBlock; - - /** - * @notice The utilization point at which the jump multiplier is applied - */ - uint256 public kink; - - event NewInterestParams( - uint256 baseRatePerBlock, - uint256 multiplierPerBlock, - uint256 jumpMultiplierPerBlock, - uint256 kink - ); - - /** - * @notice Thrown when the action is prohibited by AccessControlManager - */ - error Unauthorized(address sender, address calledContract, string methodSignature); - - /** - * @notice Construct an interest rate model - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE) - * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE) - * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point - * @param kink_ The utilization point at which the jump multiplier is applied - * @param accessControlManager_ The address of the AccessControlManager contract - */ - constructor( - uint256 baseRatePerYear, - uint256 multiplierPerYear, - uint256 jumpMultiplierPerYear, - uint256 kink_, - IAccessControlManagerV8 accessControlManager_ - ) { - require(address(accessControlManager_) != address(0), "invalid ACM address"); - - accessControlManager = accessControlManager_; - - _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); - } - - /** - * @notice Update the parameters of the interest rate model - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE) - * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE) - * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point - * @param kink_ The utilization point at which the jump multiplier is applied - * @custom:error Unauthorized if the sender is not allowed to call this function - * @custom:access Controlled by AccessControlManager - */ - function updateJumpRateModel( - uint256 baseRatePerYear, - uint256 multiplierPerYear, - uint256 jumpMultiplierPerYear, - uint256 kink_ - ) external virtual { - string memory signature = "updateJumpRateModel(uint256,uint256,uint256,uint256)"; - bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature); - - if (!isAllowedToCall) { - revert Unauthorized(msg.sender, address(this), signature); - } - - _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); - } - - /** - * @notice Calculates the current supply rate per block - * @param cash The amount of cash in the market - * @param borrows The amount of borrows in the market - * @param reserves The amount of reserves in the market - * @param reserveFactorMantissa The current reserve factor for the market - * @param badDebt The amount of badDebt in the market - * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE) - */ - function getSupplyRate( - uint256 cash, - uint256 borrows, - uint256 reserves, - uint256 reserveFactorMantissa, - uint256 badDebt - ) public view virtual override returns (uint256) { - uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa; - uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt); - uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE; - uint256 incomeToDistribute = borrows * rateToPool; - uint256 supply = cash + borrows + badDebt - reserves; - return incomeToDistribute / supply; - } - - /** - * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)` - * @param cash The amount of cash in the market - * @param borrows The amount of borrows in the market - * @param reserves The amount of reserves in the market (currently unused) - * @param badDebt The amount of badDebt in the market - * @return The utilization rate as a mantissa between [0, MANTISSA_ONE] - */ - function utilizationRate( - uint256 cash, - uint256 borrows, - uint256 reserves, - uint256 badDebt - ) public pure returns (uint256) { - // Utilization rate is 0 when there are no borrows and badDebt - if ((borrows + badDebt) == 0) { - return 0; - } - - uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves); - - if (rate > EXP_SCALE) { - rate = EXP_SCALE; - } - - return rate; - } - - /** - * @notice Internal function to update the parameters of the interest rate model - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE) - * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE) - * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point - * @param kink_ The utilization point at which the jump multiplier is applied - */ - function _updateJumpRateModel( - uint256 baseRatePerYear, - uint256 multiplierPerYear, - uint256 jumpMultiplierPerYear, - uint256 kink_ - ) internal { - baseRatePerBlock = baseRatePerYear / BLOCKS_PER_YEAR; - multiplierPerBlock = multiplierPerYear / BLOCKS_PER_YEAR; - jumpMultiplierPerBlock = jumpMultiplierPerYear / BLOCKS_PER_YEAR; - kink = kink_; - - emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); - } - - /** - * @notice Calculates the current borrow rate per block, with the error code expected by the market - * @param cash The amount of cash in the market - * @param borrows The amount of borrows in the market - * @param reserves The amount of reserves in the market - * @param badDebt The amount of badDebt in the market - * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE) - */ - function _getBorrowRate( - uint256 cash, - uint256 borrows, - uint256 reserves, - uint256 badDebt - ) internal view returns (uint256) { - uint256 util = utilizationRate(cash, borrows, reserves, badDebt); - uint256 kink_ = kink; - - if (util <= kink_) { - return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock; - } - uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock; - uint256 excessUtil; - unchecked { - excessUtil = util - kink_; - } - return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate; - } -} diff --git a/contracts/JumpRateModelV2.sol b/contracts/JumpRateModelV2.sol index 0d322145f..f458151df 100644 --- a/contracts/JumpRateModelV2.sol +++ b/contracts/JumpRateModelV2.sol @@ -2,35 +2,112 @@ pragma solidity 0.8.13; import { IAccessControlManagerV8 } from "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol"; - -import { BaseJumpRateModelV2 } from "./BaseJumpRateModelV2.sol"; +import { TimeManager } from "./TimeManager.sol"; +import { InterestRateModel } from "./InterestRateModel.sol"; +import { EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; /** - * @title Compound's JumpRateModel Contract V2 for V2 vTokens - * @author Arr00 - * @notice Supports only for V2 vTokens + * @title JumpRateModelV2 + * @author Compound (modified by Dharma Labs, Arr00 and Venus) + * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached. + * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters */ -contract JumpRateModelV2 is BaseJumpRateModelV2 { +contract JumpRateModelV2 is TimeManager, InterestRateModel { + /** + * @notice The address of the AccessControlManager contract + */ + IAccessControlManagerV8 public accessControlManager; + + /** + * @notice The multiplier of utilization rate per block or second that gives the slope of the interest rate + */ + uint256 public multiplierPerBlock; + + /** + * @notice The base interest rate per block or second which is the y-intercept when utilization rate is 0 + */ + uint256 public baseRatePerBlock; + + /** + * @notice The multiplier per block or second after hitting a specified utilization point + */ + uint256 public jumpMultiplierPerBlock; + + /** + * @notice The utilization point at which the jump multiplier is applied + */ + uint256 public kink; + + event NewInterestParams( + uint256 baseRatePerBlockOrTimestamp, + uint256 multiplierPerBlockOrTimestamp, + uint256 jumpMultiplierPerBlockOrTimestamp, + uint256 kink + ); + + /** + * @notice Thrown when the action is prohibited by AccessControlManager + */ + error Unauthorized(address sender, address calledContract, string methodSignature); + + /** + * @notice Construct an interest rate model + * @param baseRatePerYear_ The approximate target base APR, as a mantissa (scaled by EXP_SCALE) + * @param multiplierPerYear_ The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE) + * @param jumpMultiplierPerYear_ The multiplier after hitting a specified utilization point + * @param kink_ The utilization point at which the jump multiplier is applied + * @param accessControlManager_ The address of the AccessControlManager contract + * @param timeBased_ A boolean indicating whether the contract is based on time or block. + * @param blocksPerYear_ The number of blocks per year + */ constructor( + uint256 baseRatePerYear_, + uint256 multiplierPerYear_, + uint256 jumpMultiplierPerYear_, + uint256 kink_, + IAccessControlManagerV8 accessControlManager_, + bool timeBased_, + uint256 blocksPerYear_ + ) TimeManager(timeBased_, blocksPerYear_) { + require(address(accessControlManager_) != address(0), "invalid ACM address"); + + accessControlManager = accessControlManager_; + + _updateJumpRateModel(baseRatePerYear_, multiplierPerYear_, jumpMultiplierPerYear_, kink_); + } + + /** + * @notice Update the parameters of the interest rate model + * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE) + * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE) + * @param jumpMultiplierPerYear The multiplierPerBlockOrTimestamp after hitting a specified utilization point + * @param kink_ The utilization point at which the jump multiplier is applied + * @custom:error Unauthorized if the sender is not allowed to call this function + * @custom:access Controlled by AccessControlManager + */ + function updateJumpRateModel( uint256 baseRatePerYear, uint256 multiplierPerYear, uint256 jumpMultiplierPerYear, - uint256 kink_, - IAccessControlManagerV8 accessControlManager_ - ) - BaseJumpRateModelV2(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_, accessControlManager_) - /* solhint-disable-next-line no-empty-blocks */ - { + uint256 kink_ + ) external virtual { + string memory signature = "updateJumpRateModel(uint256,uint256,uint256,uint256)"; + bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature); + if (!isAllowedToCall) { + revert Unauthorized(msg.sender, address(this), signature); + } + + _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); } /** - * @notice Calculates the current borrow rate per block + * @notice Calculates the current borrow rate per slot (block or second) * @param cash The amount of cash in the market * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market * @param badDebt The amount of badDebt in the market - * @return The borrow rate percentage per block as a mantissa (scaled by 1e18) + * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by 1e18) */ function getBorrowRate( uint256 cash, @@ -40,4 +117,105 @@ contract JumpRateModelV2 is BaseJumpRateModelV2 { ) external view override returns (uint256) { return _getBorrowRate(cash, borrows, reserves, badDebt); } + + /** + * @notice Calculates the current supply rate per slot (block or second) + * @param cash The amount of cash in the market + * @param borrows The amount of borrows in the market + * @param reserves The amount of reserves in the market + * @param reserveFactorMantissa The current reserve factor for the market + * @param badDebt The amount of badDebt in the market + * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE) + */ + function getSupplyRate( + uint256 cash, + uint256 borrows, + uint256 reserves, + uint256 reserveFactorMantissa, + uint256 badDebt + ) public view virtual override returns (uint256) { + uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa; + uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt); + uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE; + uint256 incomeToDistribute = borrows * rateToPool; + uint256 supply = cash + borrows + badDebt - reserves; + return incomeToDistribute / supply; + } + + /** + * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)` + * @param cash The amount of cash in the market + * @param borrows The amount of borrows in the market + * @param reserves The amount of reserves in the market (currently unused) + * @param badDebt The amount of badDebt in the market + * @return The utilization rate as a mantissa between [0, MANTISSA_ONE] + */ + function utilizationRate( + uint256 cash, + uint256 borrows, + uint256 reserves, + uint256 badDebt + ) public pure returns (uint256) { + // Utilization rate is 0 when there are no borrows and badDebt + if ((borrows + badDebt) == 0) { + return 0; + } + + uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves); + + if (rate > EXP_SCALE) { + rate = EXP_SCALE; + } + + return rate; + } + + /** + * @notice Internal function to update the parameters of the interest rate model + * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE) + * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE) + * @param jumpMultiplierPerYear The multiplierPerBlockOrTimestamp after hitting a specified utilization point + * @param kink_ The utilization point at which the jump multiplier is applied + */ + function _updateJumpRateModel( + uint256 baseRatePerYear, + uint256 multiplierPerYear, + uint256 jumpMultiplierPerYear, + uint256 kink_ + ) internal { + baseRatePerBlock = baseRatePerYear / blocksOrSecondsPerYear; + multiplierPerBlock = multiplierPerYear / blocksOrSecondsPerYear; + jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksOrSecondsPerYear; + kink = kink_; + + emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); + } + + /** + * @notice Calculates the current borrow rate per slot (block or second), with the error code expected by the market + * @param cash The amount of cash in the market + * @param borrows The amount of borrows in the market + * @param reserves The amount of reserves in the market + * @param badDebt The amount of badDebt in the market + * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE) + */ + function _getBorrowRate( + uint256 cash, + uint256 borrows, + uint256 reserves, + uint256 badDebt + ) internal view returns (uint256) { + uint256 util = utilizationRate(cash, borrows, reserves, badDebt); + uint256 kink_ = kink; + + if (util <= kink_) { + return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock; + } + uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock; + uint256 excessUtil; + unchecked { + excessUtil = util - kink_; + } + return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate; + } } diff --git a/contracts/Lens/PoolLens.sol b/contracts/Lens/PoolLens.sol index de29c8b31..206c2f3d0 100644 --- a/contracts/Lens/PoolLens.sol +++ b/contracts/Lens/PoolLens.sol @@ -11,6 +11,7 @@ import { ComptrollerInterface, ComptrollerViewInterface } from "../ComptrollerIn import { PoolRegistryInterface } from "../Pool/PoolRegistryInterface.sol"; import { PoolRegistry } from "../Pool/PoolRegistry.sol"; import { RewardsDistributor } from "../Rewards/RewardsDistributor.sol"; +import { TimeManager } from "../TimeManager.sol"; /** * @title PoolLens @@ -25,7 +26,7 @@ import { RewardsDistributor } from "../Rewards/RewardsDistributor.sol"; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken. */ -contract PoolLens is ExponentialNoError { +contract PoolLens is TimeManager, ExponentialNoError { /** * @dev Struct for PoolDetails. */ @@ -111,10 +112,10 @@ contract PoolLens is ExponentialNoError { struct RewardTokenState { // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex uint224 index; - // The block number the index was last updated at - uint32 block; - // The block number at which to stop rewards - uint32 lastRewardingBlock; + // The block number or timestamp the index was last updated at + uint256 blockOrTimestamp; + // The block number or timestamp at which to stop rewards + uint256 lastRewardingBlockOrTimestamp; } /** @@ -134,6 +135,13 @@ contract PoolLens is ExponentialNoError { BadDebt[] badDebts; } + /** + * @param timeBased_ A boolean indicating whether the contract is based on time or block. + * @param blocksPerYear_ The number of blocks per year + * @custom:oz-upgrades-unsafe-allow constructor + */ + constructor(bool timeBased_, uint256 blocksPerYear_) TimeManager(timeBased_, blocksPerYear_) {} + /** * @notice Queries the user's supply/borrow balances in vTokens * @param vTokens The list of vToken addresses @@ -440,11 +448,17 @@ contract PoolLens is ExponentialNoError { for (uint256 i; i < markets.length; ++i) { // Market borrow and supply state we will modify update in-memory, in order to not modify storage RewardTokenState memory borrowState; - (borrowState.index, borrowState.block, borrowState.lastRewardingBlock) = rewardsDistributor - .rewardTokenBorrowState(address(markets[i])); + ( + borrowState.index, + borrowState.blockOrTimestamp, + borrowState.lastRewardingBlockOrTimestamp + ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i])); RewardTokenState memory supplyState; - (supplyState.index, supplyState.block, supplyState.lastRewardingBlock) = rewardsDistributor - .rewardTokenSupplyState(address(markets[i])); + ( + supplyState.index, + supplyState.blockOrTimestamp, + supplyState.lastRewardingBlockOrTimestamp + ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i])); Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() }); // Update market supply and borrow index in-memory @@ -481,13 +495,16 @@ contract PoolLens is ExponentialNoError { Exp memory marketBorrowIndex ) internal view { uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken); - uint256 blockNumber = block.number; + uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp(); - if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) { - blockNumber = borrowState.lastRewardingBlock; + if ( + borrowState.lastRewardingBlockOrTimestamp > 0 && + blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp + ) { + blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp; } - uint256 deltaBlocks = sub_(blockNumber, uint256(borrowState.block)); + uint256 deltaBlocks = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp); if (deltaBlocks > 0 && borrowSpeed > 0) { // Remove the total earned interest rate since the opening of the market from total borrows uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex); @@ -495,9 +512,9 @@ contract PoolLens is ExponentialNoError { Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, borrowAmount) : Double({ mantissa: 0 }); Double memory index = add_(Double({ mantissa: borrowState.index }), ratio); borrowState.index = safe224(index.mantissa, "new index overflows"); - borrowState.block = safe32(blockNumber, "block number overflows"); + borrowState.blockOrTimestamp = blockNumberOrTimestamp; } else if (deltaBlocks > 0) { - borrowState.block = safe32(blockNumber, "block number overflows"); + borrowState.blockOrTimestamp = blockNumberOrTimestamp; } } @@ -507,22 +524,25 @@ contract PoolLens is ExponentialNoError { RewardTokenState memory supplyState ) internal view { uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken); - uint256 blockNumber = block.number; + uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp(); - if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) { - blockNumber = supplyState.lastRewardingBlock; + if ( + supplyState.lastRewardingBlockOrTimestamp > 0 && + blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp + ) { + blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp; } - uint256 deltaBlocks = sub_(blockNumber, uint256(supplyState.block)); + uint256 deltaBlocks = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp); if (deltaBlocks > 0 && supplySpeed > 0) { uint256 supplyTokens = VToken(vToken).totalSupply(); uint256 tokensAccrued = mul_(deltaBlocks, supplySpeed); Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, supplyTokens) : Double({ mantissa: 0 }); Double memory index = add_(Double({ mantissa: supplyState.index }), ratio); supplyState.index = safe224(index.mantissa, "new index overflows"); - supplyState.block = safe32(blockNumber, "block number overflows"); + supplyState.blockOrTimestamp = blockNumberOrTimestamp; } else if (deltaBlocks > 0) { - supplyState.block = safe32(blockNumber, "block number overflows"); + supplyState.blockOrTimestamp = blockNumberOrTimestamp; } } diff --git a/contracts/Rewards/RewardsDistributor.sol b/contracts/Rewards/RewardsDistributor.sol index 667dc5328..cde1a0d8a 100644 --- a/contracts/Rewards/RewardsDistributor.sol +++ b/contracts/Rewards/RewardsDistributor.sol @@ -10,6 +10,7 @@ import { ExponentialNoError } from "../ExponentialNoError.sol"; import { VToken } from "../VToken.sol"; import { Comptroller } from "../Comptroller.sol"; import { MaxLoopsLimitHelper } from "../MaxLoopsLimitHelper.sol"; +import { TimeManager } from "../TimeManager.sol"; /** * @title `RewardsDistributor` @@ -26,7 +27,13 @@ import { MaxLoopsLimitHelper } from "../MaxLoopsLimitHelper.sol"; * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors. */ -contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper { +contract RewardsDistributor is + TimeManager, + ExponentialNoError, + Ownable2StepUpgradeable, + AccessControlledV8, + MaxLoopsLimitHelper +{ using SafeERC20Upgradeable for IERC20Upgradeable; struct RewardToken { @@ -38,6 +45,15 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce uint32 lastRewardingBlock; } + struct TimeBasedRewardToken { + // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex + uint224 index; + // The block timestamp the index was last updated at + uint256 timestamp; + // The block timestamp at which to stop rewards + uint256 lastRewardingTimestamp; + } + /// @notice The initial REWARD TOKEN index for a market uint224 public constant INITIAL_INDEX = 1e36; @@ -72,6 +88,12 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce IERC20Upgradeable public rewardToken; + /// @notice The REWARD TOKEN market supply state for each market + mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased; + + /// @notice The REWARD TOKEN market borrow state for each market + mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased; + /// @notice Emitted when REWARD TOKEN is distributed to a supplier event DistributedSupplierRewardToken( VToken indexed vToken, @@ -120,13 +142,25 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce /// @notice Emitted when a reward token last rewarding block for borrow is updated event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock); + /// @notice Emitted when a reward token last rewarding block timestamp for supply is updated + event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newBlock); + + /// @notice Emitted when a reward token last rewarding block timestamp for borrow is updated + event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newBlock); + modifier onlyComptroller() { require(address(comptroller) == msg.sender, "Only comptroller can call this function"); _; } - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { + /** + * @param timeBased_ A boolean indicating whether the contract is based on time or block. + * @param blocksPerYear_ The number of blocks per year + * @custom:oz-upgrades-unsafe-allow constructor + */ + constructor(bool timeBased_, uint256 blocksPerYear_) TimeManager(timeBased_, blocksPerYear_) { + // Note that the contract is upgradeable. Use initialize() or reinitializers + // to set the state variables. _disableInitializers(); } @@ -152,29 +186,18 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce _setMaxLoopsLimit(loopsLimit_); } + /** + * @notice Initializes the market state for a specific vToken + * @param vToken The address of the vToken to be initialized + * @custom:event MarketInitialized emits on success + * @custom:access Only Comptroller + */ function initializeMarket(address vToken) external onlyComptroller { - uint32 blockNumber = safe32(getBlockNumber(), "block number exceeds 32 bits"); - - RewardToken storage supplyState = rewardTokenSupplyState[vToken]; - RewardToken storage borrowState = rewardTokenBorrowState[vToken]; - - /* - * Update market state indices - */ - if (supplyState.index == 0) { - // Initialize supply state index with default value - supplyState.index = INITIAL_INDEX; - } - - if (borrowState.index == 0) { - // Initialize borrow state index with default value - borrowState.index = INITIAL_INDEX; - } + uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp(); - /* - * Update market state block numbers - */ - supplyState.block = borrowState.block = blockNumber; + isTimeBased + ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp) + : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, "block number exceeds 32 bits")); emit MarketInitialized(vToken); } @@ -240,7 +263,7 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce } /** - * @notice Set REWARD TOKEN last rewarding block for the specified markets + * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based * @param vTokens The markets whose REWARD TOKEN last rewarding block to update * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market @@ -251,6 +274,8 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce uint32[] calldata borrowLastRewardingBlocks ) external { _checkAccessAllowed("setLastRewardingBlock(address[],uint32[],uint32[])"); + require(!isTimeBased, "Block-based operation only"); + uint256 numTokens = vTokens.length; require( numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length, @@ -265,6 +290,39 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce } } + /** + * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based + * @param vTokens The markets whose REWARD TOKEN last rewarding block to update + * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market + * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market + */ + function setLastRewardingBlockTimestamps( + VToken[] calldata vTokens, + uint256[] calldata supplyLastRewardingBlockTimestamps, + uint256[] calldata borrowLastRewardingBlockTimestamps + ) external { + _checkAccessAllowed("setLastRewardingBlockTimestamps(address[],uint256[],uint256[])"); + require(isTimeBased, "Time-based operation only"); + + uint256 numTokens = vTokens.length; + require( + numTokens == supplyLastRewardingBlockTimestamps.length && + numTokens == borrowLastRewardingBlockTimestamps.length, + "RewardsDistributor::setLastRewardingBlockTimestamps invalid input" + ); + + for (uint256 i; i < numTokens; ) { + _setLastRewardingBlockTimestamp( + vTokens[i], + supplyLastRewardingBlockTimestamps[i], + borrowLastRewardingBlockTimestamps[i] + ); + unchecked { + ++i; + } + } + } + /** * @notice Set REWARD TOKEN speed for a single contributor * @param contributor The contributor whose REWARD TOKEN speed to update @@ -277,7 +335,7 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce // release storage delete lastContributorBlock[contributor]; } else { - lastContributorBlock[contributor] = getBlockNumber(); + lastContributorBlock[contributor] = getBlockNumberOrTimestamp(); } rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed; @@ -310,14 +368,14 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce */ function updateContributorRewards(address contributor) public { uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor]; - uint256 blockNumber = getBlockNumber(); - uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]); - if (deltaBlocks > 0 && rewardTokenSpeed > 0) { - uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed); + uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp(); + uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]); + if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) { + uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed); uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued); rewardTokenAccrued[contributor] = contributorAccrued; - lastContributorBlock[contributor] = blockNumber; + lastContributorBlock[contributor] = blockNumberOrTimestamp; emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]); } @@ -345,10 +403,6 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]); } - function getBlockNumber() public view virtual returns (uint256) { - return block.number; - } - /** * @notice Set REWARD TOKEN last rewarding block for a single market. * @param vToken market's whose reward token last rewarding block to be updated @@ -362,7 +416,7 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce ) internal { require(comptroller.isMarketListed(vToken), "rewardToken market is not listed"); - uint256 blockNumber = getBlockNumber(); + uint256 blockNumber = getBlockNumberOrTimestamp(); require(supplyLastRewardingBlock > blockNumber, "setting last rewarding block in the past is not allowed"); require(borrowLastRewardingBlock > blockNumber, "setting last rewarding block in the past is not allowed"); @@ -390,6 +444,55 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce } } + /** + * @notice Set REWARD TOKEN last rewarding block for a single market. + * @param vToken market's whose reward token last rewarding block to be updated + * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding block for market + * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding block for market + */ + function _setLastRewardingBlockTimestamp( + VToken vToken, + uint256 supplyLastRewardingBlockTimestamp, + uint256 borrowLastRewardingBlockTimestamp + ) internal { + require(comptroller.isMarketListed(vToken), "rewardToken market is not listed"); + + uint256 blockTimestamp = getBlockNumberOrTimestamp(); + + require( + supplyLastRewardingBlockTimestamp > blockTimestamp, + "setting last rewarding timestamp in the past is not allowed" + ); + require( + borrowLastRewardingBlockTimestamp > blockTimestamp, + "setting last rewarding timestamp in the past is not allowed" + ); + + uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)] + .lastRewardingTimestamp; + uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)] + .lastRewardingTimestamp; + + require( + currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp, + "this RewardsDistributor is already locked" + ); + require( + currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp, + "this RewardsDistributor is already locked" + ); + + if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) { + rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp; + emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp); + } + + if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) { + rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp; + emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp); + } + } + /** * @notice Set REWARD TOKEN speed for a single market. * @param vToken market's whose reward token rate to be updated @@ -430,7 +533,9 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce */ function _distributeSupplierRewardToken(address vToken, address supplier) internal { RewardToken storage supplyState = rewardTokenSupplyState[vToken]; - uint256 supplyIndex = supplyState.index; + TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken]; + + uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index; uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier]; // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN @@ -465,7 +570,9 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce */ function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal { RewardToken storage borrowState = rewardTokenBorrowState[vToken]; - uint256 borrowIndex = borrowState.index; + TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken]; + + uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index; uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower]; // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN @@ -517,28 +624,50 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce */ function _updateRewardTokenSupplyIndex(address vToken) internal { RewardToken storage supplyState = rewardTokenSupplyState[vToken]; + TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken]; + uint256 supplySpeed = rewardTokenSupplySpeeds[vToken]; - uint32 blockNumber = safe32(getBlockNumber(), "block number exceeds 32 bits"); + uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp(); - if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) { - blockNumber = supplyState.lastRewardingBlock; + if (!isTimeBased) { + safe32(blockNumberOrTimestamp, "block number exceeds 32 bits"); } - uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block)); + uint256 lastRewardingBlockOrTimestamp = isTimeBased + ? supplyStateTimeBased.lastRewardingTimestamp + : uint256(supplyState.lastRewardingBlock); - if (deltaBlocks > 0 && supplySpeed > 0) { + if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) { + blockNumberOrTimestamp = lastRewardingBlockOrTimestamp; + } + + uint256 deltaBlocksOrTimestamp = sub_( + blockNumberOrTimestamp, + (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block)) + ); + if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) { uint256 supplyTokens = VToken(vToken).totalSupply(); - uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed); + uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed); Double memory ratio = supplyTokens > 0 ? fraction(accruedSinceUpdate, supplyTokens) : Double({ mantissa: 0 }); - supplyState.index = safe224( - add_(Double({ mantissa: supplyState.index }), ratio).mantissa, + uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index; + uint224 index = safe224( + add_(Double({ mantissa: supplyIndex }), ratio).mantissa, "new index exceeds 224 bits" ); - supplyState.block = blockNumber; - } else if (deltaBlocks > 0) { - supplyState.block = blockNumber; + + if (isTimeBased) { + supplyStateTimeBased.index = index; + supplyStateTimeBased.timestamp = blockNumberOrTimestamp; + } else { + supplyState.index = index; + supplyState.block = uint32(blockNumberOrTimestamp); + } + } else if (deltaBlocksOrTimestamp > 0) { + isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32( + blockNumberOrTimestamp + ); } emit RewardTokenSupplyIndexUpdated(vToken); @@ -552,29 +681,110 @@ contract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, Acce */ function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal { RewardToken storage borrowState = rewardTokenBorrowState[vToken]; + TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken]; + uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken]; - uint32 blockNumber = safe32(getBlockNumber(), "block number exceeds 32 bits"); + uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp(); + + if (!isTimeBased) { + safe32(blockNumberOrTimestamp, "block number exceeds 32 bits"); + } + + uint256 lastRewardingBlockOrTimestamp = isTimeBased + ? borrowStateTimeBased.lastRewardingTimestamp + : uint256(borrowState.lastRewardingBlock); - if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) { - blockNumber = borrowState.lastRewardingBlock; + if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) { + blockNumberOrTimestamp = lastRewardingBlockOrTimestamp; } - uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block)); - if (deltaBlocks > 0 && borrowSpeed > 0) { + uint256 deltaBlocksOrTimestamp = sub_( + blockNumberOrTimestamp, + (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block)) + ); + if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) { uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex); - uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed); + uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed); Double memory ratio = borrowAmount > 0 ? fraction(accruedSinceUpdate, borrowAmount) : Double({ mantissa: 0 }); - borrowState.index = safe224( - add_(Double({ mantissa: borrowState.index }), ratio).mantissa, + uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index; + uint224 index = safe224( + add_(Double({ mantissa: borrowIndex }), ratio).mantissa, "new index exceeds 224 bits" ); - borrowState.block = blockNumber; - } else if (deltaBlocks > 0) { - borrowState.block = blockNumber; + + if (isTimeBased) { + borrowStateTimeBased.index = index; + borrowStateTimeBased.timestamp = blockNumberOrTimestamp; + } else { + borrowState.index = index; + borrowState.block = uint32(blockNumberOrTimestamp); + } + } else if (deltaBlocksOrTimestamp > 0) { + if (isTimeBased) { + borrowStateTimeBased.timestamp = blockNumberOrTimestamp; + } else { + borrowState.block = uint32(blockNumberOrTimestamp); + } } emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex); } + + /** + * @notice Initializes the market state for a specific vToken called when contract is block-based + * @param vToken The address of the vToken to be initialized + * @param blockNumber current block number + */ + function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal { + RewardToken storage supplyState = rewardTokenSupplyState[vToken]; + RewardToken storage borrowState = rewardTokenBorrowState[vToken]; + + /* + * Update market state indices + */ + if (supplyState.index == 0) { + // Initialize supply state index with default value + supplyState.index = INITIAL_INDEX; + } + + if (borrowState.index == 0) { + // Initialize borrow state index with default value + borrowState.index = INITIAL_INDEX; + } + + /* + * Update market state block numbers + */ + supplyState.block = borrowState.block = blockNumber; + } + + /** + * @notice Initializes the market state for a specific vToken called when contract is time-based + * @param vToken The address of the vToken to be initialized + * @param blockTimestamp current block timestamp + */ + function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal { + TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken]; + TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[vToken]; + + /* + * Update market state indices + */ + if (supplyState.index == 0) { + // Initialize supply state index with default value + supplyState.index = INITIAL_INDEX; + } + + if (borrowState.index == 0) { + // Initialize borrow state index with default value + borrowState.index = INITIAL_INDEX; + } + + /* + * Update market state block timestamp + */ + supplyState.timestamp = borrowState.timestamp = blockTimestamp; + } } diff --git a/contracts/Shortfall/Shortfall.sol b/contracts/Shortfall/Shortfall.sol index 79e61d5e1..4f3c51ffc 100644 --- a/contracts/Shortfall/Shortfall.sol +++ b/contracts/Shortfall/Shortfall.sol @@ -8,6 +8,7 @@ import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/ import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol"; import { VToken } from "../VToken.sol"; +import { TimeManager } from "../TimeManager.sol"; import { ComptrollerInterface, ComptrollerViewInterface } from "../ComptrollerInterface.sol"; import { IRiskFund } from "../RiskFund/IRiskFund.sol"; import { PoolRegistry } from "../Pool/PoolRegistry.sol"; @@ -26,7 +27,13 @@ import { EXP_SCALE } from "../lib/constants.sol"; * if the risk fund covers the pool's bad debt plus the 10% incentive, then the auction winner is determined by who will take the smallest percentage of the * risk fund in exchange for paying off all the pool's bad debt. */ -contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGuardUpgradeable, TokenDebtTracker { +contract Shortfall is + TimeManager, + Ownable2StepUpgradeable, + AccessControlledV8, + ReentrancyGuardUpgradeable, + TokenDebtTracker +{ using SafeERC20Upgradeable for IERC20Upgradeable; /// @notice Type of auction @@ -44,14 +51,16 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua /// @notice Auction metadata struct Auction { - uint256 startBlock; + /// @notice It holds either the starting block number or timestamp + uint256 startBlockOrTimestamp; AuctionType auctionType; AuctionStatus status; VToken[] markets; uint256 seizedRiskFund; address highestBidder; uint256 highestBidBps; - uint256 highestBidBlock; + /// @notice It holds either the highestBid block or timestamp + uint256 highestBidBlockOrTimestamp; uint256 startBidBps; mapping(VToken => uint256) marketDebt; mapping(VToken => uint256) bidAmount; @@ -60,11 +69,20 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua /// @dev Max basis points i.e., 100% uint256 private constant MAX_BPS = 10000; + // @notice Default block limit for the next bidder to place a bid uint256 private constant DEFAULT_NEXT_BIDDER_BLOCK_LIMIT = 100; + // @notice Default number of blocks to wait for the first bidder before starting the auction uint256 private constant DEFAULT_WAIT_FOR_FIRST_BIDDER = 100; - uint256 private constant DEFAULT_INCENTIVE_BPS = 1000; // 10% + // @notice Default block timestamp limit for the next bidder to place a bid + uint256 private constant DEFAULT_NEXT_BIDDER_BLOCK_TIMESTAMP_LIMIT = 300; + + // @notice Default time limit in seconds for the first bidder to place a bid before the auction starts + uint256 private constant DEFAULT_WAIT_FOR_FIRST_BIDDER_IN_SECONDS = 300; + + // @notice Default incentive basis points (BPS) for the auction participants, set to 10% + uint256 private constant DEFAULT_INCENTIVE_BPS = 1000; /// @notice Pool registry address address public poolRegistry; @@ -78,13 +96,13 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua /// @notice Incentive to auction participants, initial value set to 1000 or 10% uint256 public incentiveBps; - /// @notice Time to wait for next bidder. Initially waits for 100 blocks + /// @notice Time to wait for next bidder. Initially waits for 100 blocks or 300 seconds uint256 public nextBidderBlockLimit; /// @notice Boolean of if auctions are paused bool public auctionsPaused; - /// @notice Time to wait for first bidder. Initially waits for 100 blocks + /// @notice Time to wait for first bidder. Initially waits for 100 blocks or 300 seconds uint256 public waitForFirstBidder; /// @notice Auctions for each pool @@ -93,7 +111,7 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua /// @notice Emitted when a auction starts event AuctionStarted( address indexed comptroller, - uint256 auctionStartBlock, + uint256 auctionStartBlockOrTimestamp, AuctionType auctionType, VToken[] markets, uint256[] marketsDebt, @@ -102,12 +120,17 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua ); /// @notice Emitted when a bid is placed - event BidPlaced(address indexed comptroller, uint256 auctionStartBlock, uint256 bidBps, address indexed bidder); + event BidPlaced( + address indexed comptroller, + uint256 auctionStartBlockOrTimestamp, + uint256 bidBps, + address indexed bidder + ); /// @notice Emitted when a auction is completed event AuctionClosed( address indexed comptroller, - uint256 auctionStartBlock, + uint256 auctionStartBlockOrTimestamp, address indexed highestBidder, uint256 highestBidBps, uint256 seizedRiskFind, @@ -116,7 +139,7 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua ); /// @notice Emitted when a auction is restarted - event AuctionRestarted(address indexed comptroller, uint256 auctionStartBlock); + event AuctionRestarted(address indexed comptroller, uint256 auctionStartBlockOrTimestamp); /// @notice Emitted when pool registry address is updated event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry); @@ -124,11 +147,14 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua /// @notice Emitted when minimum pool bad debt is updated event MinimumPoolBadDebtUpdated(uint256 oldMinimumPoolBadDebt, uint256 newMinimumPoolBadDebt); - /// @notice Emitted when wait for first bidder block count is updated + /// @notice Emitted when wait for first bidder block or timestamp count is updated event WaitForFirstBidderUpdated(uint256 oldWaitForFirstBidder, uint256 newWaitForFirstBidder); - /// @notice Emitted when next bidder block limit is updated - event NextBidderBlockLimitUpdated(uint256 oldNextBidderBlockLimit, uint256 newNextBidderBlockLimit); + /// @notice Emitted when next bidder block or timestamp limit is updated + event NextBidderBlockLimitUpdated( + uint256 oldNextBidderBlockOrTimestampLimit, + uint256 newNextBidderBlockOrTimestampLimit + ); /// @notice Emitted when incentiveBps is updated event IncentiveBpsUpdated(uint256 oldIncentiveBps, uint256 newIncentiveBps); @@ -139,8 +165,12 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua /// @notice Emitted when auctions are unpaused event AuctionsResumed(address sender); - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { + /** + * @param timeBased_ A boolean indicating whether the contract is based on time or block. + * @param blocksPerYear_ The number of blocks per year + * @custom:oz-upgrades-unsafe-allow constructor + */ + constructor(bool timeBased_, uint256 blocksPerYear_) TimeManager(timeBased_, blocksPerYear_) { // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. _disableInitializers(); @@ -168,23 +198,29 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua __TokenDebtTracker_init(); minimumPoolBadDebt = minimumPoolBadDebt_; riskFund = riskFund_; - waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER; - nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_LIMIT; incentiveBps = DEFAULT_INCENTIVE_BPS; auctionsPaused = false; + + if (isTimeBased) { + waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER_IN_SECONDS; + nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_TIMESTAMP_LIMIT; + } else { + waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER; + nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_LIMIT; + } } /** * @notice Place a bid greater than the previous in an ongoing auction * @param comptroller Comptroller address of the pool * @param bidBps The bid percent of the risk fund or bad debt depending on auction type - * @param auctionStartBlock The block number when auction started + * @param auctionStartBlockOrTimestamp The block number or timestamp when auction started * @custom:event Emits BidPlaced event on success */ - function placeBid(address comptroller, uint256 bidBps, uint256 auctionStartBlock) external nonReentrant { + function placeBid(address comptroller, uint256 bidBps, uint256 auctionStartBlockOrTimestamp) external nonReentrant { Auction storage auction = auctions[comptroller]; - require(auction.startBlock == auctionStartBlock, "auction has been restarted"); + require(auction.startBlockOrTimestamp == auctionStartBlockOrTimestamp, "auction has been restarted"); require(_isStarted(auction), "no on-going auction"); require(!_isStale(auction), "auction is stale, restart it"); require(bidBps > 0, "basis points cannot be zero"); @@ -222,9 +258,9 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua auction.highestBidder = msg.sender; auction.highestBidBps = bidBps; - auction.highestBidBlock = block.number; + auction.highestBidBlockOrTimestamp = getBlockNumberOrTimestamp(); - emit BidPlaced(comptroller, auction.startBlock, bidBps, msg.sender); + emit BidPlaced(comptroller, auction.startBlockOrTimestamp, bidBps, msg.sender); } /** @@ -237,7 +273,8 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua require(_isStarted(auction), "no on-going auction"); require( - block.number > auction.highestBidBlock + nextBidderBlockLimit && auction.highestBidder != address(0), + getBlockNumberOrTimestamp() > auction.highestBidBlockOrTimestamp + nextBidderBlockLimit && + auction.highestBidder != address(0), "waiting for next bidder. cannot close auction" ); @@ -273,7 +310,7 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua emit AuctionClosed( comptroller, - auction.startBlock, + auction.startBlockOrTimestamp, auction.highestBidder, auction.highestBidBps, transferredAmount, @@ -307,22 +344,22 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua auction.status = AuctionStatus.ENDED; - emit AuctionRestarted(comptroller, auction.startBlock); + emit AuctionRestarted(comptroller, auction.startBlockOrTimestamp); _startAuction(comptroller); } /** - * @notice Update next bidder block limit which is used determine when an auction can be closed - * @param _nextBidderBlockLimit New next bidder block limit + * @notice Update next bidder block or timestamp limit which is used determine when an auction can be closed + * @param _nextBidderBlockOrTimestampLimit New next bidder block limit * @custom:event Emits NextBidderBlockLimitUpdated on success * @custom:access Restricted by ACM */ - function updateNextBidderBlockLimit(uint256 _nextBidderBlockLimit) external { + function updateNextBidderBlockLimit(uint256 _nextBidderBlockOrTimestampLimit) external { _checkAccessAllowed("updateNextBidderBlockLimit(uint256)"); - require(_nextBidderBlockLimit != 0, "_nextBidderBlockLimit must not be 0"); - uint256 oldNextBidderBlockLimit = nextBidderBlockLimit; - nextBidderBlockLimit = _nextBidderBlockLimit; - emit NextBidderBlockLimitUpdated(oldNextBidderBlockLimit, _nextBidderBlockLimit); + require(_nextBidderBlockOrTimestampLimit != 0, "_nextBidderBlockOrTimestampLimit must not be 0"); + + emit NextBidderBlockLimitUpdated(nextBidderBlockLimit, _nextBidderBlockOrTimestampLimit); + nextBidderBlockLimit = _nextBidderBlockOrTimestampLimit; } /** @@ -353,8 +390,8 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua } /** - * @notice Update wait for first bidder block count. If the first bid is not made within this limit, the auction is closed and needs to be restarted - * @param _waitForFirstBidder New wait for first bidder block count + * @notice Update wait for first bidder block or timestamp count. If the first bid is not made within this limit, the auction is closed and needs to be restarted + * @param _waitForFirstBidder New wait for first bidder block or timestamp count * @custom:event Emits WaitForFirstBidderUpdated on success * @custom:access Restricted by ACM */ @@ -421,7 +458,7 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua ); auction.highestBidBps = 0; - auction.highestBidBlock = 0; + auction.highestBidBlockOrTimestamp = 0; uint256 marketsCount = auction.markets.length; for (uint256 i; i < marketsCount; ++i) { @@ -473,13 +510,13 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua } auction.seizedRiskFund = riskFundBalance - remainingRiskFundBalance; - auction.startBlock = block.number; + auction.startBlockOrTimestamp = getBlockNumberOrTimestamp(); auction.status = AuctionStatus.STARTED; auction.highestBidder = address(0); emit AuctionStarted( comptroller, - auction.startBlock, + auction.startBlockOrTimestamp, auction.auctionType, auction.markets, marketsDebt, @@ -517,12 +554,12 @@ contract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGua /** * @dev Checks if the auction is stale, i.e. there's no bidder and the auction - * was started more than waitForFirstBidder blocks ago. + * was started more than waitForFirstBidder blocks or seconds ago. * @param auction The auction to query the status for * @return True if the auction is stale */ function _isStale(Auction storage auction) internal view returns (bool) { bool noBidder = auction.highestBidder == address(0); - return noBidder && (block.number > auction.startBlock + waitForFirstBidder); + return noBidder && (getBlockNumberOrTimestamp() > auction.startBlockOrTimestamp + waitForFirstBidder); } } diff --git a/contracts/TimeManager.sol b/contracts/TimeManager.sol new file mode 100644 index 000000000..b8d4585a5 --- /dev/null +++ b/contracts/TimeManager.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.13; + +import { SECONDS_PER_YEAR } from "./lib/constants.sol"; + +abstract contract TimeManager { + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + uint256 public immutable blocksOrSecondsPerYear; + + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + bool public immutable isTimeBased; + + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + function() view returns (uint256) private immutable _getCurrentSlot; + + /// @notice Thrown on invaid arguments + error InvalidBlocksPerYear(); + + /** + * @param timeBased_ A boolean indicating whether the contract is based on time or block. + * If timeBased is true than blocksPerYear_ param is ignored as blocksOrSecondsPerYear is set to SECONDS_PER_YEAR + * @param blocksPerYear_ The number of blocks per year + * @custom:error InvalidBlocksPerYear is thrown if blocksPerYear entered is zero + * @custom:oz-upgrades-unsafe-allow constructor + */ + constructor(bool timeBased_, uint256 blocksPerYear_) { + if (!timeBased_ && blocksPerYear_ == 0) { + revert InvalidBlocksPerYear(); + } + + isTimeBased = timeBased_; + blocksOrSecondsPerYear = timeBased_ ? SECONDS_PER_YEAR : blocksPerYear_; + _getCurrentSlot = timeBased_ ? _getBlockTimestamp : _getBlockNumber; + } + + /** + * @dev Function to simply retrieve block number or block timestamp + * This exists mainly for inheriting test contracts to stub this result. + * @return Current block number or block timestamp + */ + function getBlockNumberOrTimestamp() public view virtual returns (uint256) { + return _getCurrentSlot(); + } + + /** + * @notice Returns the current timestamp in seconds + * @return The current timestamp + */ + function _getBlockTimestamp() private view returns (uint256) { + return block.timestamp; + } + + /** + * @notice Returns the current block number + * @return The current block number + */ + function _getBlockNumber() private view returns (uint256) { + return block.number; + } +} diff --git a/contracts/VToken.sol b/contracts/VToken.sol index 15aa34578..fde2e3a67 100644 --- a/contracts/VToken.sol +++ b/contracts/VToken.sol @@ -12,6 +12,7 @@ import { ComptrollerInterface, ComptrollerViewInterface } from "./ComptrollerInt import { TokenErrorReporter } from "./ErrorReporter.sol"; import { InterestRateModel } from "./InterestRateModel.sol"; import { ExponentialNoError } from "./ExponentialNoError.sol"; +import { TimeManager } from "./TimeManager.sol"; import { ensureNonzeroAddress } from "./lib/validators.sol"; /** @@ -41,6 +42,7 @@ import { ensureNonzeroAddress } from "./lib/validators.sol"; * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below. */ contract VToken is + TimeManager, Ownable2StepUpgradeable, AccessControlledV8, VTokenInterface, @@ -65,8 +67,12 @@ contract VToken is _notEntered = true; // get a gas-refund post-Istanbul } - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { + /** + * @param timeBased_ A boolean indicating whether the contract is based on time or block. + * @param blocksPerYear_ The number of blocks per year + * @custom:oz-upgrades-unsafe-allow constructor + */ + constructor(bool timeBased_, uint256 blocksPerYear_) TimeManager(timeBased_, blocksPerYear_) { // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. _disableInitializers(); @@ -424,7 +430,7 @@ contract VToken is */ function reduceReserves(uint256 reduceAmount) external override nonReentrant { accrueInterest(); - if (reduceReservesBlockNumber == _getBlockNumber()) return; + if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return; _reduceReservesFresh(reduceAmount); } @@ -614,8 +620,8 @@ contract VToken is } /** - * @notice A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve - * @param _newReduceReservesBlockDelta block difference value + * @notice A public function to set new threshold of slot(block/second) difference after which funds will be sent to the protocol share reserve + * @param _newReduceReservesBlockDelta slot(block/second) difference value * @custom:access Only Governance */ function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockDelta) external { @@ -673,16 +679,16 @@ contract VToken is } /** - * @notice Returns the current per-block borrow interest rate for this vToken - * @return rate The borrow interest rate per block, scaled by 1e18 + * @notice Returns the current per-slot(block/second) borrow interest rate for this vToken + * @return rate The borrow interest rate per slot(block/second), scaled by 1e18 */ function borrowRatePerBlock() external view override returns (uint256) { return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt); } /** - * @notice Returns the current per-block supply interest rate for this v - * @return rate The supply interest rate per block, scaled by 1e18 + * @notice Returns the current per-slot(block/second) supply interest rate for this v + * @return rate The supply interest rate per slot(block/second), scaled by 1e18 */ function supplyRatePerBlock() external view override returns (uint256) { return @@ -724,21 +730,21 @@ contract VToken is /** * @notice Applies accrued interest to total borrows and reserves - * @dev This calculates interest accrued from the last checkpointed block - * up to the current block and writes new checkpoint to storage and + * @dev This calculates interest accrued from the last checkpointed slot(block/second) + * up to the current slot(block/second) and writes new checkpoint to storage and * reduce spread reserves to protocol share reserve - * if currentBlock - reduceReservesBlockNumber >= blockDelta + * if currentSlot - reduceReservesBlockNumber >= slotDelta * @return Always NO_ERROR * @custom:event Emits AccrueInterest event on success * @custom:access Not restricted */ function accrueInterest() public virtual override returns (uint256) { /* Remember the initial block number */ - uint256 currentBlockNumber = _getBlockNumber(); - uint256 accrualBlockNumberPrior = accrualBlockNumber; + uint256 currentSlotNumber = getBlockNumberOrTimestamp(); + uint256 accrualSlotNumberPrior = accrualBlockNumber; /* Short-circuit accumulating 0 interest */ - if (accrualBlockNumberPrior == currentBlockNumber) { + if (accrualSlotNumberPrior == currentSlotNumber) { return NO_ERROR; } @@ -752,19 +758,19 @@ contract VToken is uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt); require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, "borrow rate is absurdly high"); - /* Calculate the number of blocks elapsed since the last accrual */ - uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior; + /* Calculate the number of slots elapsed since the last accrual */ + uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior; /* * Calculate the interest accumulated into borrows and reserves and the new index: - * simpleInterestFactor = borrowRate * blockDelta + * simpleInterestFactor = borrowRate * slotDelta * interestAccumulated = simpleInterestFactor * totalBorrows * totalBorrowsNew = interestAccumulated + totalBorrows * totalReservesNew = interestAccumulated * reserveFactor + totalReserves * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex */ - Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta); + Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta); uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior); uint256 totalBorrowsNew = interestAccumulated + borrowsPrior; uint256 totalReservesNew = mul_ScalarTruncateAddUInt( @@ -779,13 +785,13 @@ contract VToken is // (No safe failures beyond this point) /* We write the previously calculated values into storage */ - accrualBlockNumber = currentBlockNumber; + accrualBlockNumber = currentSlotNumber; borrowIndex = borrowIndexNew; totalBorrows = totalBorrowsNew; totalReserves = totalReservesNew; - if (currentBlockNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) { - reduceReservesBlockNumber = currentBlockNumber; + if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) { + reduceReservesBlockNumber = currentSlotNumber; _reduceReservesFresh(totalReservesNew); } @@ -806,8 +812,8 @@ contract VToken is /* Fail if mint not allowed */ comptroller.preMintHook(address(this), minter, mintAmount); - /* Verify market's block number equals current block number */ - if (accrualBlockNumber != _getBlockNumber()) { + /* Verify market's slot(block/second) number equals current slot(block/second) number */ + if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert MintFreshnessCheck(); } @@ -850,7 +856,7 @@ contract VToken is /** * @notice User redeems vTokens in exchange for the underlying asset - * @dev Assumes interest has already been accrued up to the current block + * @dev Assumes interest has already been accrued up to the current slot(block/second) * @param redeemer The address of the account which is redeeming the tokens * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero) * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero) @@ -858,8 +864,8 @@ contract VToken is function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal { require(redeemTokensIn == 0 || redeemAmountIn == 0, "one of redeemTokensIn or redeemAmountIn must be zero"); - /* Verify market's block number equals current block number */ - if (accrualBlockNumber != _getBlockNumber()) { + /* Verify market's slot(block/second) number equals current slot(block/second) number */ + if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert RedeemFreshnessCheck(); } @@ -936,8 +942,8 @@ contract VToken is /* Fail if borrow not allowed */ comptroller.preBorrowHook(address(this), borrower, borrowAmount); - /* Verify market's block number equals current block number */ - if (accrualBlockNumber != _getBlockNumber()) { + /* Verify market's slot(block/second) number equals current slot(block/second) number */ + if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert BorrowFreshnessCheck(); } @@ -989,8 +995,8 @@ contract VToken is /* Fail if repayBorrow not allowed */ comptroller.preRepayHook(address(this), borrower); - /* Verify market's block number equals current block number */ - if (accrualBlockNumber != _getBlockNumber()) { + /* Verify market's slot(block/second) number equals current slot(block/second) number */ + if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert RepayBorrowFreshnessCheck(); } @@ -1085,13 +1091,13 @@ contract VToken is skipLiquidityCheck ); - /* Verify market's block number equals current block number */ - if (accrualBlockNumber != _getBlockNumber()) { + /* Verify market's slot(block/second) number equals current slot(block/second) number */ + if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert LiquidateFreshnessCheck(); } - /* Verify vTokenCollateral market's block number equals current block number */ - if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) { + /* Verify vTokenCollateral market's slot(block/second) number equals current slot(block/second) number */ + if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) { revert LiquidateCollateralFreshnessCheck(); } @@ -1213,8 +1219,8 @@ contract VToken is * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18) */ function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal { - // Verify market's block number equals current block number - if (accrualBlockNumber != _getBlockNumber()) { + // Verify market's slot(block/second) number equals current slot(block/second) number + if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert SetReserveFactorFreshCheck(); } @@ -1240,8 +1246,8 @@ contract VToken is uint256 totalReservesNew; uint256 actualAddAmount; - // We fail gracefully unless market's block number equals current block number - if (accrualBlockNumber != _getBlockNumber()) { + // We fail gracefully unless market's slot(block/second) number equals current slot(block/second) number + if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert AddReservesFactorFreshCheck(actualAddAmount); } @@ -1265,8 +1271,8 @@ contract VToken is // totalReserves - reduceAmount uint256 totalReservesNew; - // We fail gracefully unless market's block number equals current block number - if (accrualBlockNumber != _getBlockNumber()) { + // We fail gracefully unless market's slot(block/second) number equals current slot(block/second) number + if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert ReduceReservesFreshCheck(); } @@ -1312,8 +1318,8 @@ contract VToken is // Used to store old model for use in the event that is emitted on success InterestRateModel oldInterestRateModel; - // We fail gracefully unless market's block number equals current block number - if (accrualBlockNumber != _getBlockNumber()) { + // We fail gracefully unless market's slot(block/second) number equals current slot(block/second) number + if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert SetInterestRateModelFreshCheck(); } @@ -1443,11 +1449,11 @@ contract VToken is _setComptroller(comptroller_); - // Initialize block number and borrow index (block number mocks depend on comptroller being set) - accrualBlockNumber = _getBlockNumber(); + // Initialize slot(block/second) number and borrow index (slot(block/second) number mocks depend on comptroller being set) + accrualBlockNumber = getBlockNumberOrTimestamp(); borrowIndex = MANTISSA_ONE; - // Set the interest rate model (depends on block number / borrow index) + // Set the interest rate model (depends on slot(block/second) number / borrow index) _setInterestRateModelFresh(interestRateModel_); _setReserveFactorFresh(reserveFactorMantissa_); @@ -1491,15 +1497,6 @@ contract VToken is return IERC20Upgradeable(underlying).balanceOf(address(this)); } - /** - * @dev Function to simply retrieve block number - * This exists mainly for inheriting test contracts to stub this result. - * @return Current block number - */ - function _getBlockNumber() internal view virtual returns (uint256) { - return block.number; - } - /** * @notice Return the borrow balance of account based on stored data * @param account The address whose balance should be calculated diff --git a/contracts/VTokenInterfaces.sol b/contracts/VTokenInterfaces.sol index fea37715c..172ac5ee6 100644 --- a/contracts/VTokenInterfaces.sol +++ b/contracts/VTokenInterfaces.sol @@ -79,7 +79,7 @@ contract VTokenStorage { uint256 public reserveFactorMantissa; /** - * @notice Block number that interest was last accrued at + * @notice Slot(block/second) number that interest was last accrued at */ uint256 public accrualBlockNumber; diff --git a/contracts/WhitePaperInterestRateModel.sol b/contracts/WhitePaperInterestRateModel.sol index beeed30ea..fe4c880db 100644 --- a/contracts/WhitePaperInterestRateModel.sol +++ b/contracts/WhitePaperInterestRateModel.sol @@ -2,45 +2,53 @@ pragma solidity 0.8.13; import { InterestRateModel } from "./InterestRateModel.sol"; -import { BLOCKS_PER_YEAR, EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; +import { TimeManager } from "./TimeManager.sol"; +import { EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; /** * @title Compound's WhitePaperInterestRateModel Contract * @author Compound * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper */ -contract WhitePaperInterestRateModel is InterestRateModel { +contract WhitePaperInterestRateModel is TimeManager, InterestRateModel { /** - * @notice The multiplier of utilization rate that gives the slope of the interest rate + * @notice The multiplier of utilization rate per block or second that gives the slope of the interest rate */ uint256 public immutable multiplierPerBlock; /** - * @notice The base interest rate which is the y-intercept when utilization rate is 0 + * @notice The base interest rate per block or second which is the y-intercept when utilization rate is 0 */ uint256 public immutable baseRatePerBlock; - event NewInterestParams(uint256 baseRatePerBlock, uint256 multiplierPerBlock); + event NewInterestParams(uint256 baseRatePerBlockOrTimestamp, uint256 multiplierPerBlockOrTimestamp); /** * @notice Construct an interest rate model - * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE) - * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE) + * @param baseRatePerYear_ The approximate target base APR, as a mantissa (scaled by EXP_SCALE) + * @param multiplierPerYear_ The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE) + * @param timeBased_ A boolean indicating whether the contract is based on time or block. + * @param blocksPerYear_ The number of blocks per year */ - constructor(uint256 baseRatePerYear, uint256 multiplierPerYear) { - baseRatePerBlock = baseRatePerYear / BLOCKS_PER_YEAR; - multiplierPerBlock = multiplierPerYear / BLOCKS_PER_YEAR; + constructor( + uint256 baseRatePerYear_, + uint256 multiplierPerYear_, + bool timeBased_, + uint256 blocksPerYear_ + ) TimeManager(timeBased_, blocksPerYear_) { + baseRatePerBlock = baseRatePerYear_ / blocksOrSecondsPerYear; + multiplierPerBlock = multiplierPerYear_ / blocksOrSecondsPerYear; emit NewInterestParams(baseRatePerBlock, multiplierPerBlock); } /** - * @notice Calculates the current borrow rate per block, with the error code expected by the market + * @notice Calculates the current borrow rate per slot(block/second), with the error code expected by the market * @param cash The amount of cash in the market * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market * @param badDebt The amount of badDebt in the market - * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE) + * @return The borrow rate percentage per slot(block/second) as a mantissa (scaled by EXP_SCALE) */ function getBorrowRate( uint256 cash, @@ -53,13 +61,13 @@ contract WhitePaperInterestRateModel is InterestRateModel { } /** - * @notice Calculates the current supply rate per block + * @notice Calculates the current supply rate per slot(block/second) * @param cash The amount of cash in the market * @param borrows The amount of borrows in the market * @param reserves The amount of reserves in the market * @param reserveFactorMantissa The current reserve factor for the market * @param badDebt The amount of badDebt in the market - * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE) + * @return The supply rate percentage per slot(block/second) as a mantissa (scaled by EXP_SCALE) */ function getSupplyRate( uint256 cash, diff --git a/contracts/lib/constants.sol b/contracts/lib/constants.sol index 6e1225f23..766f2fe17 100644 --- a/contracts/lib/constants.sol +++ b/contracts/lib/constants.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BSD-3-Clause pragma solidity 0.8.13; -/// @dev The approximate number of blocks per year that is assumed by the interest rate model -uint256 constant BLOCKS_PER_YEAR = 10_512_000; +/// @dev The approximate number of seconds per year +uint256 constant SECONDS_PER_YEAR = 31_536_000; /// @dev Base unit for computations, usually used in scaling (multiplications, divisions) uint256 constant EXP_SCALE = 1e18; diff --git a/contracts/test/UpgradedVToken.sol b/contracts/test/UpgradedVToken.sol index de86227ca..1739641d3 100644 --- a/contracts/test/UpgradedVToken.sol +++ b/contracts/test/UpgradedVToken.sol @@ -13,6 +13,17 @@ import { InterestRateModel } from "../InterestRateModel.sol"; * @author Venus */ contract UpgradedVToken is VToken { + /** + * @param timeBased_ A boolean indicating whether the contract is based on time or block. + * @param blocksPerYear_ The number of blocks per year + * @custom:oz-upgrades-unsafe-allow constructor + */ + constructor(bool timeBased_, uint256 blocksPerYear_) VToken(timeBased_, blocksPerYear_) { + // Note that the contract is upgradeable. Use initialize() or reinitializers + // to set the state variables. + _disableInitializers(); + } + /** * @notice Construct a new money market * @param underlying_ The address of the underlying asset diff --git a/contracts/test/VTokenHarness.sol b/contracts/test/VTokenHarness.sol index 42b1c2c90..a1a4045a3 100644 --- a/contracts/test/VTokenHarness.sol +++ b/contracts/test/VTokenHarness.sol @@ -13,6 +13,17 @@ contract VTokenHarness is VToken { mapping(address => bool) public failTransferToAddresses; + /** + * @param timeBased_ A boolean indicating whether the contract is based on time or block. + * @param blocksPerYear_ The number of blocks per year + * @custom:oz-upgrades-unsafe-allow constructor + */ + constructor(bool timeBased_, uint256 blocksPerYear_) VToken(timeBased_, blocksPerYear_) { + // Note that the contract is upgradeable. Use initialize() or reinitializers + // to set the state variables. + _disableInitializers(); + } + function harnessSetAccrualBlockNumber(uint256 accrualBlockNumber_) external { accrualBlockNumber = accrualBlockNumber_; } @@ -119,6 +130,10 @@ contract VTokenHarness is VToken { comptroller.preBorrowHook(address(this), msg.sender, amount); } + function getBlockNumberOrTimestamp() public view override returns (uint256) { + return blockNumber; + } + function _doTransferOut(address to, uint256 amount) internal override { require(failTransferToAddresses[to] == false, "HARNESS_TOKEN_TRANSFER_OUT_FAILED"); return super._doTransferOut(to, amount); @@ -130,8 +145,4 @@ contract VTokenHarness is VToken { } return super._exchangeRateStored(); } - - function _getBlockNumber() internal view override returns (uint256) { - return blockNumber; - } } diff --git a/deploy/003-price-oracle-configure-feeds.ts b/deploy/003-price-oracle-configure-feeds.ts index 024e064fd..7dc5ce911 100644 --- a/deploy/003-price-oracle-configure-feeds.ts +++ b/deploy/003-price-oracle-configure-feeds.ts @@ -1,4 +1,4 @@ -import configureOracleFeeds from "@venusprotocol/oracle/dist/deploy/2-configure-feeds"; +import configureOracleFeeds from "@venusprotocol/oracle/dist/deploy/3-configure-feeds"; import { HardhatRuntimeEnvironment } from "hardhat/types"; configureOracleFeeds.tags = ["Oracle"]; diff --git a/deploy/007-deploy-pool-lens.ts b/deploy/007-deploy-pool-lens.ts index 1222f368a..f5c564d01 100644 --- a/deploy/007-deploy-pool-lens.ts +++ b/deploy/007-deploy-pool-lens.ts @@ -1,14 +1,18 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { getBlockOrTimestampBasedDeploymentInfo } from "../helpers/deploymentUtils"; + const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; const { deploy } = deployments; const { deployer } = await getNamedAccounts(); + const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre); + await deploy("PoolLens", { from: deployer, - args: [], + args: [isTimeBased, blocksPerYear], log: true, autoMine: true, }); diff --git a/deploy/009-deploy-vtokens.ts b/deploy/009-deploy-vtokens.ts index ebe95e4ef..f05b93039 100644 --- a/deploy/009-deploy-vtokens.ts +++ b/deploy/009-deploy-vtokens.ts @@ -7,9 +7,8 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { getConfig, getTokenConfig } from "../helpers/deploymentConfig"; import { InterestRateModels } from "../helpers/deploymentConfig"; -import { getUnregisteredVTokens, toAddress } from "../helpers/deploymentUtils"; - -const ADDRESS_ONE = "0x0000000000000000000000000000000000000001"; +import { getBlockOrTimestampBasedDeploymentInfo, getUnregisteredVTokens, toAddress } from "../helpers/deploymentUtils"; +import { AddressOne } from "../helpers/utils"; const mantissaToBps = (num: BigNumberish) => { return BigNumber.from(num).div(parseUnits("1", 14)).toString(); @@ -21,6 +20,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployer } = await getNamedAccounts(); const { tokensConfig, poolConfig, preconfiguredAddresses } = await getConfig(hre.network.name); + const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre); + const accessControlManagerAddress = await toAddress( preconfiguredAddresses.AccessControlManager || "AccessControlManager", hre, @@ -30,7 +31,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const vTokenImpl: DeployResult = await deploy("VTokenImpl", { contract: "VToken", from: deployer, - args: [], + args: [isTimeBased, blocksPerYear], log: true, autoMine: true, }); @@ -80,7 +81,15 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const result: DeployResult = await deploy(rateModelName, { from: deployer, contract: "JumpRateModelV2", - args: [baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_, accessControlManagerAddress], + args: [ + baseRatePerYear, + multiplierPerYear, + jumpMultiplierPerYear, + kink_, + accessControlManagerAddress, + isTimeBased, + blocksPerYear, + ], log: true, autoMine: true, }); @@ -92,7 +101,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const result: DeployResult = await deploy(rateModelName, { from: deployer, contract: "WhitePaperInterestRateModel", - args: [baseRatePerYear, multiplierPerYear], + args: [baseRatePerYear, multiplierPerYear, isTimeBased, blocksPerYear], log: true, autoMine: true, }); @@ -114,10 +123,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { vTokenDecimals, preconfiguredAddresses.NormalTimelock || deployer, // admin accessControlManagerAddress, - [ - preconfiguredAddresses.Shortfall || ADDRESS_ONE, - preconfiguredAddresses.ProtocolShareReserve || treasuryAddress, - ], + [AddressOne, treasuryAddress], reserveFactor, ]; await deploy(`VToken_${symbol}`, { diff --git a/deploy/010-deploy-reward-distributors.ts b/deploy/010-deploy-reward-distributors.ts index 059c64467..78e919cab 100644 --- a/deploy/010-deploy-reward-distributors.ts +++ b/deploy/010-deploy-reward-distributors.ts @@ -3,7 +3,11 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { getConfig, getTokenAddress, getTokenConfig } from "../helpers/deploymentConfig"; -import { getUnregisteredRewardsDistributors, toAddress } from "../helpers/deploymentUtils"; +import { + getBlockOrTimestampBasedDeploymentInfo, + getUnregisteredRewardsDistributors, + toAddress, +} from "../helpers/deploymentUtils"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; @@ -12,6 +16,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const maxLoopsLimit = 100; const { tokensConfig, poolConfig, preconfiguredAddresses } = await getConfig(hre.network.name); + const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre); const accessControlAddress = await toAddress( preconfiguredAddresses.AccessControlManager || "AccessControlManager", @@ -25,6 +30,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { contract: "RewardsDistributor", from: deployer, autoMine: true, + args: [isTimeBased, blocksPerYear], log: true, skipIfAlreadyDeployed: true, }); @@ -52,6 +58,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }, upgradeIndex: 0, }, + args: [isTimeBased, blocksPerYear], autoMine: true, log: true, skipIfAlreadyDeployed: true, diff --git a/deploy/011-initial-liquidity.ts b/deploy/011-initial-liquidity.ts index 63f4ed545..bd36fa462 100644 --- a/deploy/011-initial-liquidity.ts +++ b/deploy/011-initial-liquidity.ts @@ -10,7 +10,7 @@ import { getConfig, getTokenConfig, } from "../helpers/deploymentConfig"; -import { getUnderlyingMock, getUnderlyingToken, getUnregisteredVTokens } from "../helpers/deploymentUtils"; +import { getUnderlyingMock, getUnderlyingToken, getUnregisteredVTokens, toAddress } from "../helpers/deploymentUtils"; const sumAmounts = async (tokens: { symbol: string; amount: BigNumber }[]) => { const amounts: { [symbol: string]: BigNumber } = {}; @@ -44,8 +44,8 @@ const faucetTokens = async (deploymentConfig: DeploymentConfig, hre: HardhatRunt } }; -const approveTimelock = async (deploymentConfig: DeploymentConfig, hre: HardhatRuntimeEnvironment) => { - if (hre.network.name !== "bsctestnet") { +const sendInitialLiquidityToTreasury = async (deploymentConfig: DeploymentConfig, hre: HardhatRuntimeEnvironment) => { + if (hre.network.name == "bscmainnet" || hre.network.name == "ethereum") { return; } const { poolConfig, tokensConfig, preconfiguredAddresses } = deploymentConfig; @@ -59,8 +59,13 @@ const approveTimelock = async (deploymentConfig: DeploymentConfig, hre: HardhatR const totalAmounts = await sumAmounts(amounts); for (const [symbol, amount] of Object.entries(totalAmounts)) { const tokenContract = await getUnderlyingToken(symbol, tokensConfig); - console.log(`Approving ${amount} ${symbol} to Timelock`); - const tx = await tokenContract.approve(preconfiguredAddresses.NormalTimelock, amount, { gasLimit: 5000000 }); + console.log(`Sending ${amount} ${symbol} to VTreasury`); + console.log(`Token Contract: ${tokenContract.address}`); + console.log(`Token Contract: ${amount.toString()}`); + const treasuryAddress = await toAddress(preconfiguredAddresses.VTreasury || "VTreasury", hre); + console.log(`Token Contract: ${treasuryAddress}`); + + const tx = await tokenContract.transfer(treasuryAddress, amount, { gasLimit: 5000000 }); await tx.wait(1); } }; @@ -68,7 +73,7 @@ const approveTimelock = async (deploymentConfig: DeploymentConfig, hre: HardhatR const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const deploymentConfig = await getConfig(hre.network.name); await faucetTokens(deploymentConfig, hre); - await approveTimelock(deploymentConfig, hre); + await sendInitialLiquidityToTreasury(deploymentConfig, hre); }; func.tags = ["InitialLiquidity", "il"]; diff --git a/deploy/013-vip-based-config.ts b/deploy/013-vip-based-config.ts index 72902a4a7..acaf7f6af 100644 --- a/deploy/013-vip-based-config.ts +++ b/deploy/013-vip-based-config.ts @@ -177,36 +177,23 @@ const transferInitialLiquidity = async ( deploymentConfig: DeploymentConfig, hre: HardhatRuntimeEnvironment, ): Promise => { - const { deployer } = await hre.getNamedAccounts(); + if (!hre.network.live) { + return []; + } const { preconfiguredAddresses, tokensConfig } = deploymentConfig; const { asset, initialSupply } = vTokenConfig; const token = getTokenConfig(asset, tokensConfig); const tokenContract = await getUnderlyingToken(token.symbol, tokensConfig); - - if (hre.network.name === "bsctestnet") { - console.log(`Adding a command to transfer ${initialSupply} ${token.symbol} to Timelock`); - return [ - { - contract: tokenContract.address, - signature: "transferFrom(address,address,uint256)", - argTypes: ["address", "address", "uint256"], - parameters: [deployer, preconfiguredAddresses.NormalTimelock, initialSupply], - value: 0, - }, - ]; - } else if (hre.network.name === "bscmainnet") { - console.log(`Adding a command to withdraw ${initialSupply} ${token.symbol} to Timelock`); - return [ - { - contract: preconfiguredAddresses.VTreasury, - signature: "withdrawTreasuryBEP20(address,uint256,address)", - argTypes: ["address", "uint256", "address"], - parameters: [tokenContract.address, initialSupply, preconfiguredAddresses.NormalTimelock], - value: 0, - }, - ]; - } - return []; + console.log(`Adding a command to withdraw ${initialSupply} ${token.symbol} to Timelock from Treasury`); + return [ + { + contract: preconfiguredAddresses.VTreasury, + signature: "withdrawTreasuryToken(address,uint256,address)", + argTypes: ["address", "uint256", "address"], + parameters: [tokenContract.address, initialSupply, preconfiguredAddresses.NormalTimelock], + value: 0, + }, + ]; }; const approvePoolRegistry = async ( @@ -318,7 +305,7 @@ const hasPermission = async ( caller: string, hre: HardhatRuntimeEnvironment, ): Promise => { - const role = makeRole(hre.network.name === "bscmainnet", targetContract, method); + const role = makeRole(hre.network.live, targetContract, method); return accessControl.hasRole(role, caller); }; diff --git a/deploy/014-riskfund-protocolshare.ts b/deploy/014-riskfund-protocolshare.ts index 01184f79e..b645ffee8 100644 --- a/deploy/014-riskfund-protocolshare.ts +++ b/deploy/014-riskfund-protocolshare.ts @@ -4,7 +4,7 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { getConfig } from "../helpers/deploymentConfig"; -import { getUnderlyingToken, toAddress } from "../helpers/deploymentUtils"; +import { getBlockOrTimestampBasedDeploymentInfo, getUnderlyingToken, toAddress } from "../helpers/deploymentUtils"; import { convertToUnit } from "../helpers/utils"; import { Comptroller } from "../typechain"; @@ -19,6 +19,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { tokensConfig, preconfiguredAddresses } = await getConfig(hre.network.name); const usdt = await getUnderlyingToken("USDT", tokensConfig); + const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre); + const poolRegistry = await ethers.getContract("PoolRegistry"); const deployerSigner = ethers.provider.getSigner(deployer); const swapRouterAddress = await toAddress(preconfiguredAddresses.SwapRouter_CorePool || "SwapRouter", hre); @@ -69,6 +71,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }, upgradeIndex: 0, }, + args: [isTimeBased, blocksPerYear], autoMine: true, log: true, }); diff --git a/deploy/015-transfer-funds-ownership.ts b/deploy/015-transfer-funds-ownership.ts new file mode 100644 index 000000000..e36ef4db2 --- /dev/null +++ b/deploy/015-transfer-funds-ownership.ts @@ -0,0 +1,47 @@ +import { ethers } from "hardhat"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +import { ETHEREUM_MULTISIG, SEPOLIA_MULTISIG } from "../helpers/deploymentConfig"; + +interface Config { + [key: string]: string; +} + +const TESTNET_MNEMONIC_SIGNER = "0xFA747c4a62c4D168276329F822d004026A1c05E9"; // signer[1] from testnet mnemonic + +const targetOwners: Config = { + hardhat: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", // signer[1] from hardhat mnemonic + bsctestnet: TESTNET_MNEMONIC_SIGNER, + bscmainnet: "0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396", // NORMAL VIP Timelock + sepolia: SEPOLIA_MULTISIG, + ethereum: ETHEREUM_MULTISIG, +}; + +const contracts = ["RiskFund", "Shortfall", "ProtocolShareReserve"]; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + await transfer2StepOwnerships(contracts, hre.network.name); +}; + +const transfer2StepOwnerships = async (contractNames: string[], networkName: string) => { + for (const contractName of contractNames) { + const contract = await ethers.getContract(contractName); + const owner = await contract.owner(); + + let tx; + if (owner !== targetOwners[networkName]) { + tx = await contract.transferOwnership(targetOwners[networkName]); + await tx.wait(1); + const pendingOwner = await contract.pendingOwner(); + console.log( + `${contractName} owner ${owner} sucessfully changed to ${pendingOwner}. Please accept the ownership.`, + ); + } else { + console.error(`${contractName} owner ${owner} is equal to target ownership address ${targetOwners[networkName]}`); + } + } +}; + +func.tags = ["TransferFundsOwnership"]; +export default func; diff --git a/deployments/bscmainnet.json b/deployments/bscmainnet.json index 6b4f19163..5a5dc50e6 100644 --- a/deployments/bscmainnet.json +++ b/deployments/bscmainnet.json @@ -2913,6 +2913,307 @@ } ] }, + "JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps": { + "address": "0x53DbE3c0d1Bd439E4F600ad36791C41d02906E6b", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] + }, "JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink5000bps": { "address": "0x35DAcdbFa83369d9EdAc586c65FF4Aba850F1DBa", "abi": [ @@ -6852,160 +7153,143 @@ } ] }, - "ProtocolShareReserve": { - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "RewardsDistributorImpl": { + "address": "0x01251D4eF6bb9f56C8Bef7D3A201f00f4C122589", "abi": [ { - "anonymous": false, + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" }, { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "MaxLoopsLimitExceeded", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "sender", "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "calledContract", "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "admin", - "outputs": [ + }, { - "internalType": "address", - "name": "admin_", - "type": "address" + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "Unauthorized", + "type": "error" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newAdmin", + "name": "vToken", "type": "address" - } - ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "implementation", - "outputs": [ + }, { - "internalType": "address", - "name": "implementation_", - "type": "address" + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "contributor", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" } ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "contributor", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint256", + "name": "rewardAccrued", + "type": "uint256" } ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" + "name": "ContributorRewardsUpdated", + "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, - "internalType": "address", - "name": "comptroller", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "asset", + "name": "borrower", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", "type": "uint256" } ], - "name": "AssetsReservesUpdated", + "name": "DistributedBorrowerRewardToken", "type": "event" }, { @@ -7013,24 +7297,36 @@ "inputs": [ { "indexed": true, - "internalType": "address", - "name": "comptroller", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "asset", + "name": "supplier", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", "type": "uint256" } ], - "name": "FundsReleased", + "name": "DistributedSupplierRewardToken", "type": "event" }, { @@ -7052,17 +7348,49 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketInitialized", + "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": true, + "indexed": false, "internalType": "address", - "name": "newOwner", + "name": "newAccessControlManager", "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "NewAccessControlManager", "type": "event" }, { @@ -7081,7 +7409,7 @@ "type": "address" } ], - "name": "OwnershipTransferred", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -7090,17 +7418,17 @@ { "indexed": true, "internalType": "address", - "name": "oldPoolRegistry", + "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "newPoolRegistry", + "name": "newOwner", "type": "address" } ], - "name": "PoolRegistryUpdated", + "name": "OwnershipTransferred", "type": "event" }, { @@ -7109,101 +7437,123 @@ { "indexed": true, "internalType": "address", - "name": "token", + "name": "vToken", "type": "address" }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "RewardTokenBorrowIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, - "internalType": "address", - "name": "to", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "newSpeed", "type": "uint256" } ], - "name": "SweepToken", + "name": "RewardTokenBorrowSpeedUpdated", "type": "event" }, { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "recipient", "type": "address" - } - ], - "name": "assetsReserves", - "outputs": [ + }, { + "indexed": false, "internalType": "uint256", - "name": "", + "name": "amount", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "RewardTokenGranted", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", + "name": "vToken", "type": "address" } ], - "name": "getPoolAssetReserve", - "outputs": [ + "name": "RewardTokenSupplyIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, { + "indexed": false, "internalType": "uint256", - "name": "", + "name": "newSpeed", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "RewardTokenSupplySpeedUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "protocolIncome_", + "name": "vToken", "type": "address" }, { - "internalType": "address", - "name": "riskFund_", - "type": "address" + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SupplyLastRewardingBlockUpdated", + "type": "event" }, { "inputs": [], - "name": "owner", + "name": "INITIAL_INDEX", "outputs": [ { - "internalType": "address", + "internalType": "uint224", "name": "", - "type": "address" + "type": "uint224" } ], "stateMutability": "view", @@ -7211,10 +7561,17 @@ }, { "inputs": [], - "name": "pendingOwner", + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -7223,75 +7580,92 @@ "type": "function" }, { - "inputs": [], - "name": "poolRegistry", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "holder", "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" } ], - "stateMutability": "view", + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "protocolIncome", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "holder", "type": "address" } ], - "stateMutability": "view", + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" }, { "internalType": "address", - "name": "asset", + "name": "borrower", "type": "address" }, { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "releaseFunds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" } ], + "name": "distributeBorrowerRewardToken", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "renounceOwnership", + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", + "type": "address" + } + ], + "name": "distributeSupplierRewardToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "riskFund", + "name": "getBlockNumber", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", @@ -7301,11 +7675,16 @@ "inputs": [ { "internalType": "address", - "name": "poolRegistry_", + "name": "recipient", "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "setPoolRegistry", + "name": "grantRewardToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -7313,17 +7692,27 @@ { "inputs": [ { - "internalType": "address", - "name": "_token", + "internalType": "contract Comptroller", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", "type": "address" }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + }, { "internalType": "address", - "name": "_to", + "name": "accessControlManager_", "type": "address" } ], - "name": "sweepToken", + "name": "initialize", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -7332,11 +7721,11 @@ "inputs": [ { "internalType": "address", - "name": "newOwner", + "name": "vToken", "type": "address" } ], - "name": "transferOwnership", + "name": "initializeMarket", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -7345,206 +7734,169 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" - }, + } + ], + "name": "lastContributorBlock", + "outputs": [ { - "internalType": "address", - "name": "asset", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "updateAssetsState", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ { - "internalType": "address", - "name": "_logic", - "type": "address" - }, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ { "internalType": "address", - "name": "admin_", + "name": "", "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" } ], - "stateMutability": "payable", - "type": "constructor" - } - ] - }, - "ProtocolShareReserve_Implementation": { - "address": "0xc1c56732FcaFca0F66D59745Ec69DC642EC20ab8", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ + "name": "pendingOwner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", + "name": "", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "AssetsReservesUpdated", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "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": "FundsReleased", - "type": "event" + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "rewardToken", + "outputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" } ], - "name": "Initialized", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "", "type": "address" - }, + } + ], + "name": "rewardTokenAccrued", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "", "type": "address" - }, + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "OwnershipTransferred", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "oldPoolRegistry", + "name": "", "type": "address" + } + ], + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" }, { - "indexed": true, - "internalType": "address", - "name": "newPoolRegistry", - "type": "address" + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" } ], - "name": "PoolRegistryUpdated", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "token", + "name": "", "type": "address" }, { - "indexed": true, "internalType": "address", - "name": "to", + "name": "", "type": "address" - }, + } + ], + "name": "rewardTokenBorrowerIndex", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "", "type": "uint256" } ], - "name": "SweepToken", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -7555,7 +7907,7 @@ "type": "address" } ], - "name": "assetsReserves", + "name": "rewardTokenContributorSpeeds", "outputs": [ { "internalType": "uint256", @@ -7570,16 +7922,16 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" }, { "internalType": "address", - "name": "asset", + "name": "", "type": "address" } ], - "name": "getPoolAssetReserve", + "name": "rewardTokenSupplierIndex", "outputs": [ { "internalType": "uint256", @@ -7594,130 +7946,113 @@ "inputs": [ { "internalType": "address", - "name": "protocolIncome_", - "type": "address" - }, - { - "internalType": "address", - "name": "riskFund_", + "name": "", "type": "address" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", + "name": "rewardTokenSupplySpeeds", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "poolRegistry", + "name": "rewardTokenSupplyState", "outputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "protocolIncome", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "accessControlManager_", "type": "address" } ], - "stateMutability": "view", + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", + "name": "contributor", "type": "address" }, { "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "releaseFunds", - "outputs": [ - { - "internalType": "uint256", - "name": "", + "name": "rewardTokenSpeed", "type": "uint256" } ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", + "name": "setContributorRewardTokenSpeed", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "riskFund", - "outputs": [ + "inputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" } ], - "stateMutability": "view", + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "poolRegistry_", - "type": "address" + "internalType": "uint256", + "name": "limit", + "type": "uint256" } ], - "name": "setPoolRegistry", + "name": "setMaxLoopsLimit", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -7725,17 +8060,22 @@ { "inputs": [ { - "internalType": "address", - "name": "_token", - "type": "address" + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" }, { - "internalType": "address", - "name": "_to", - "type": "address" + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" } ], - "name": "sweepToken", + "name": "setRewardTokenSpeeds", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -7757,46 +8097,58 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", + "name": "contributor", "type": "address" } ], - "name": "updateAssetsState", + "name": "updateContributorRewards", "outputs": [], "stateMutability": "nonpayable", "type": "function" - } - ] - }, - "ProtocolShareReserve_Proxy": { - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", - "abi": [ + }, { "inputs": [ { "internalType": "address", - "name": "_logic", + "name": "vToken", "type": "address" }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "admin_", + "name": "vToken", "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" } ], - "stateMutability": "payable", - "type": "constructor" - }, + "name": "updateRewardTokenSupplyIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "RewardsDistributor_DeFi_0": { + "address": "0x7524116CEC937ef17B5998436F16d1306c4F7EF8", + "abi": [ { "anonymous": false, "inputs": [ @@ -7919,16 +8271,6 @@ { "stateMutability": "payable", "type": "receive" - } - ] - }, - "RewardsDistributorImpl": { - "address": "0x01251D4eF6bb9f56C8Bef7D3A201f00f4C122589", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" }, { "inputs": [ @@ -8912,11 +9254,181 @@ "outputs": [], "stateMutability": "nonpayable", "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" } ] }, - "RewardsDistributor_DeFi_0": { + "RewardsDistributor_DeFi_0_Proxy": { "address": "0x7524116CEC937ef17B5998436F16d1306c4F7EF8", + "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" + } + ] + }, + "RewardsDistributor_DeFi_1": { + "address": "0x14d9A428D0f35f81A30ca8D8b2F3974D3CccB98B", "abi": [ { "anonymous": false, @@ -10047,8 +10559,8 @@ } ] }, - "RewardsDistributor_DeFi_0_Proxy": { - "address": "0x7524116CEC937ef17B5998436F16d1306c4F7EF8", + "RewardsDistributor_DeFi_1_Proxy": { + "address": "0x14d9A428D0f35f81A30ca8D8b2F3974D3CccB98B", "abi": [ { "inputs": [ @@ -10196,8 +10708,8 @@ } ] }, - "RewardsDistributor_DeFi_1": { - "address": "0x14d9A428D0f35f81A30ca8D8b2F3974D3CccB98B", + "RewardsDistributor_DeFi_2": { + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", "abi": [ { "anonymous": false, @@ -11328,8 +11840,8 @@ } ] }, - "RewardsDistributor_DeFi_1_Proxy": { - "address": "0x14d9A428D0f35f81A30ca8D8b2F3974D3CccB98B", + "RewardsDistributor_DeFi_2_Proxy": { + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", "abi": [ { "inputs": [ @@ -19163,8 +19675,8 @@ } ] }, - "RewardsDistributor_Stablecoins_0": { - "address": "0xBA711976CdF8CF3288bF721f758fB764503Eb1f6", + "RewardsDistributor_LiquidStakedBNB_4": { + "address": "0x888E317606b4c590BBAD88653863e8B345702633", "abi": [ { "anonymous": false, @@ -20295,8 +20807,8 @@ } ] }, - "RewardsDistributor_Stablecoins_0_Proxy": { - "address": "0xBA711976CdF8CF3288bF721f758fB764503Eb1f6", + "RewardsDistributor_LiquidStakedBNB_4_Proxy": { + "address": "0x888E317606b4c590BBAD88653863e8B345702633", "abi": [ { "inputs": [ @@ -20444,8 +20956,8 @@ } ] }, - "RewardsDistributor_Stablecoins_1": { - "address": "0xA31185D804BF9209347698128984a43A67Ce6d11", + "RewardsDistributor_Stablecoins_0": { + "address": "0xBA711976CdF8CF3288bF721f758fB764503Eb1f6", "abi": [ { "anonymous": false, @@ -21576,8 +22088,8 @@ } ] }, - "RewardsDistributor_Stablecoins_1_Proxy": { - "address": "0xA31185D804BF9209347698128984a43A67Ce6d11", + "RewardsDistributor_Stablecoins_0_Proxy": { + "address": "0xBA711976CdF8CF3288bF721f758fB764503Eb1f6", "abi": [ { "inputs": [ @@ -21725,8 +22237,8 @@ } ] }, - "RewardsDistributor_Stablecoins_2": { - "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "RewardsDistributor_Stablecoins_1": { + "address": "0xA31185D804BF9209347698128984a43A67Ce6d11", "abi": [ { "anonymous": false, @@ -22857,8 +23369,8 @@ } ] }, - "RewardsDistributor_Stablecoins_2_Proxy": { - "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "RewardsDistributor_Stablecoins_1_Proxy": { + "address": "0xA31185D804BF9209347698128984a43A67Ce6d11", "abi": [ { "inputs": [ @@ -23006,8 +23518,8 @@ } ] }, - "RewardsDistributor_Tron_0": { - "address": "0x804F3893d3c1C3EFFDf778eDDa7C199129235882", + "RewardsDistributor_Stablecoins_2": { + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", "abi": [ { "anonymous": false, @@ -24138,8 +24650,8 @@ } ] }, - "RewardsDistributor_Tron_0_Proxy": { - "address": "0x804F3893d3c1C3EFFDf778eDDa7C199129235882", + "RewardsDistributor_Stablecoins_2_Proxy": { + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", "abi": [ { "inputs": [ @@ -24287,8 +24799,8 @@ } ] }, - "RewardsDistributor_Tron_1": { - "address": "0x6536123503DF76BDfF8207e4Fb0C594Bc5eFD00A", + "RewardsDistributor_Tron_0": { + "address": "0x804F3893d3c1C3EFFDf778eDDa7C199129235882", "abi": [ { "anonymous": false, @@ -25419,8 +25931,8 @@ } ] }, - "RewardsDistributor_Tron_1_Proxy": { - "address": "0x6536123503DF76BDfF8207e4Fb0C594Bc5eFD00A", + "RewardsDistributor_Tron_0_Proxy": { + "address": "0x804F3893d3c1C3EFFDf778eDDa7C199129235882", "abi": [ { "inputs": [ @@ -25568,8 +26080,8 @@ } ] }, - "RewardsDistributor_Tron_2": { - "address": "0x22af8a65639a351a9D5d77d5a25ea5e1Cf5e9E6b", + "RewardsDistributor_Tron_1": { + "address": "0x6536123503DF76BDfF8207e4Fb0C594Bc5eFD00A", "abi": [ { "anonymous": false, @@ -26700,8 +27212,8 @@ } ] }, - "RewardsDistributor_Tron_2_Proxy": { - "address": "0x22af8a65639a351a9D5d77d5a25ea5e1Cf5e9E6b", + "RewardsDistributor_Tron_1_Proxy": { + "address": "0x6536123503DF76BDfF8207e4Fb0C594Bc5eFD00A", "abi": [ { "inputs": [ @@ -26849,8 +27361,8 @@ } ] }, - "RewardsDistributor_Tron_3": { - "address": "0x08e4AFd80A5849FDBa4bBeea86ed470D697e4C54", + "RewardsDistributor_Tron_2": { + "address": "0x22af8a65639a351a9D5d77d5a25ea5e1Cf5e9E6b", "abi": [ { "anonymous": false, @@ -27981,8 +28493,8 @@ } ] }, - "RewardsDistributor_Tron_3_Proxy": { - "address": "0x08e4AFd80A5849FDBa4bBeea86ed470D697e4C54", + "RewardsDistributor_Tron_2_Proxy": { + "address": "0x22af8a65639a351a9D5d77d5a25ea5e1Cf5e9E6b", "abi": [ { "inputs": [ @@ -28130,8 +28642,8 @@ } ] }, - "RiskFund": { - "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "RewardsDistributor_Tron_3": { + "address": "0x08e4AFd80A5849FDBa4bBeea86ed470D697e4C54", "abi": [ { "anonymous": false, @@ -28256,11 +28768,6 @@ "stateMutability": "payable", "type": "receive" }, - { - "inputs": [], - "name": "ApproveFailed", - "type": "error" - }, { "inputs": [ { @@ -28299,9 +28806,23 @@ "type": "error" }, { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" }, { "anonymous": false, @@ -28309,42 +28830,110 @@ { "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "contributor", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "contributor", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "rewardAccrued", "type": "uint256" } ], - "name": "AssetsReservesUpdated", + "name": "ContributorRewardsUpdated", "type": "event" }, { "anonymous": false, "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, { "indexed": true, "internalType": "address", - "name": "oldConvertibleBaseAsset", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "newConvertibleBaseAsset", + "name": "supplier", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", + "type": "uint256" } ], - "name": "ConvertibleBaseAssetUpdated", + "name": "DistributedSupplierRewardToken", "type": "event" }, { @@ -28364,19 +28953,13 @@ "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "oldMaxLoopsLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newmaxLoopsLimit", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" } ], - "name": "MaxLoopsLimitUpdated", + "name": "MarketInitialized", "type": "event" }, { @@ -28385,17 +28968,17 @@ { "indexed": false, "internalType": "uint256", - "name": "oldMinAmountToConvert", + "name": "oldMaxLoopsLimit", "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "newMinAmountToConvert", + "name": "newmaxLoopsLimit", "type": "uint256" } ], - "name": "MinAmountToConvertUpdated", + "name": "MaxLoopsLimitUpdated", "type": "event" }, { @@ -28461,17 +29044,24 @@ { "indexed": true, "internalType": "address", - "name": "oldPancakeSwapRouter", + "name": "vToken", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newPancakeSwapRouter", - "type": "address" + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" } ], - "name": "PancakeSwapRouterUpdated", + "name": "RewardTokenBorrowIndexUpdated", "type": "event" }, { @@ -28479,18 +29069,18 @@ "inputs": [ { "indexed": true, - "internalType": "address", - "name": "oldPoolRegistry", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newPoolRegistry", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" } ], - "name": "PoolRegistryUpdated", + "name": "RewardTokenBorrowSpeedUpdated", "type": "event" }, { @@ -28499,42 +29089,30 @@ { "indexed": true, "internalType": "address", - "name": "oldShortfallContract", + "name": "recipient", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newShortfallContract", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "ShortfallContractUpdated", + "name": "RewardTokenGranted", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address[]", - "name": "markets", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "amountsOutMin", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalAmount", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" } ], - "name": "SwappedPoolsAssets", + "name": "RewardTokenSupplyIndexUpdated", "type": "event" }, { @@ -28542,24 +29120,18 @@ "inputs": [ { "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "newSpeed", "type": "uint256" } ], - "name": "SweepToken", + "name": "RewardTokenSupplySpeedUpdated", "type": "event" }, { @@ -28568,19 +29140,32 @@ { "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" }, { "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" } ], - "name": "TransferredReserveForAuction", + "name": "SupplyLastRewardingBlockUpdated", "type": "event" }, + { + "inputs": [], + "name": "INITIAL_INDEX", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "acceptOwnership", @@ -28605,67 +29190,84 @@ "inputs": [ { "internalType": "address", - "name": "", + "name": "holder", "type": "address" - } - ], - "name": "assetsReserves", - "outputs": [ + }, { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" } ], - "stateMutability": "view", + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "convertibleBaseAsset", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "holder", "type": "address" } ], - "stateMutability": "view", + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" }, { "internalType": "address", - "name": "asset", + "name": "borrower", "type": "address" - } - ], - "name": "getPoolAssetReserve", - "outputs": [ + }, { - "internalType": "uint256", - "name": "", - "type": "uint256" + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" } ], - "stateMutability": "view", + "name": "distributeBorrowerRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", "type": "address" } ], - "name": "getPoolsBaseAssetReserves", + "name": "distributeSupplierRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", "outputs": [ { "internalType": "uint256", @@ -28680,28 +29282,41 @@ "inputs": [ { "internalType": "address", - "name": "pancakeSwapRouter_", + "name": "recipient", "type": "address" }, { "internalType": "uint256", - "name": "minAmountToConvert_", + "name": "amount", "type": "uint256" - }, + } + ], + "name": "grantRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "internalType": "address", - "name": "convertibleBaseAsset_", + "internalType": "contract Comptroller", + "name": "comptroller_", "type": "address" }, { - "internalType": "address", - "name": "accessControlManager_", + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", "type": "address" }, { "internalType": "uint256", "name": "loopsLimit_", "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" } ], "name": "initialize", @@ -28710,8 +29325,27 @@ "type": "function" }, { - "inputs": [], - "name": "maxLoopsLimit", + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "initializeMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastContributorBlock", "outputs": [ { "internalType": "uint256", @@ -28724,7 +29358,7 @@ }, { "inputs": [], - "name": "minAmountToConvert", + "name": "maxLoopsLimit", "outputs": [ { "internalType": "uint256", @@ -28750,7 +29384,7 @@ }, { "inputs": [], - "name": "pancakeSwapRouter", + "name": "pendingOwner", "outputs": [ { "internalType": "address", @@ -28763,10 +29397,17 @@ }, { "inputs": [], - "name": "pendingOwner", + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rewardToken", "outputs": [ { - "internalType": "address", + "internalType": "contract IERC20Upgradeable", "name": "", "type": "address" } @@ -28775,177 +29416,273 @@ "type": "function" }, { - "inputs": [], - "name": "poolRegistry", - "outputs": [ + "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], + "name": "rewardTokenAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "accessControlManager_", + "name": "", "type": "address" } ], - "name": "setAccessControlManager", - "outputs": [], - "stateMutability": "nonpayable", + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "_convertibleBaseAsset", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", "type": "address" } ], - "name": "setConvertibleBaseAsset", - "outputs": [], - "stateMutability": "nonpayable", + "name": "rewardTokenBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenContributorSpeeds", + "outputs": [ { "internalType": "uint256", - "name": "limit", + "name": "", "type": "uint256" } ], - "name": "setMaxLoopsLimit", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplierIndex", + "outputs": [ { "internalType": "uint256", - "name": "minAmountToConvert_", + "name": "", "type": "uint256" } ], - "name": "setMinAmountToConvert", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "pancakeSwapRouter_", + "name": "", "type": "address" } ], - "name": "setPancakeSwapRouter", - "outputs": [], - "stateMutability": "nonpayable", + "name": "rewardTokenSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "poolRegistry_", + "name": "", "type": "address" } ], - "name": "setPoolRegistry", - "outputs": [], - "stateMutability": "nonpayable", + "name": "rewardTokenSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "shortfallContractAddress_", + "name": "accessControlManager_", "type": "address" } ], - "name": "setShortfallContractAddress", + "name": "setAccessControlManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "shortfall", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "contributor", "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardTokenSpeed", + "type": "uint256" } ], - "stateMutability": "view", + "name": "setContributorRewardTokenSpeed", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address[]", - "name": "markets", + "internalType": "contract VToken[]", + "name": "vTokens", "type": "address[]" }, { - "internalType": "uint256[]", - "name": "amountsOutMin", - "type": "uint256[]" - }, - { - "internalType": "address[][]", - "name": "paths", - "type": "address[][]" + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" } ], - "name": "swapPoolsAssets", - "outputs": [ + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "limit", "type": "uint256" } ], + "name": "setMaxLoopsLimit", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "_token", - "type": "address" + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" }, { - "internalType": "address", - "name": "_to", - "type": "address" + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" } ], - "name": "sweepToken", + "name": "setRewardTokenSpeeds", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -28967,23 +29704,12 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "contributor", "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferReserveForAuction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" } ], + "name": "updateContributorRewards", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -28991,16 +29717,36 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "asset", + "name": "vToken", "type": "address" } ], - "name": "updateAssetsState", + "name": "updateRewardTokenSupplyIndex", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -29028,19 +29774,286 @@ } ] }, - "RiskFund_Implementation": { - "address": "0x87ac8dD81Ec00D2183a04D22884e7FC67f6ce0C8", + "RewardsDistributor_Tron_3_Proxy": { + "address": "0x08e4AFd80A5849FDBa4bBeea86ed470D697e4C54", "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ApproveFailed", - "type": "error" - }, + { + "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" + } + ] + }, + "RiskFund": { + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "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": "ApproveFailed", + "type": "error" + }, { "inputs": [ { @@ -29784,12 +30797,7 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" - } - ] - }, - "RiskFund_Proxy": { - "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", - "abi": [ + }, { "inputs": [ { @@ -29810,308 +30818,52 @@ ], "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" } ] }, - "Shortfall": { - "address": "0xf37530A8a810Fcb501AA0Ecd0B0699388F0F2209", + "RiskFund_Implementation": { + "address": "0x0E8Ef0EC1e0C109c5B5249CcefB703A414835eaC", "abi": [ { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "corePoolComptroller_", "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_", + "name": "vbnb_", "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, { "internalType": "address", - "name": "newAdmin", + "name": "nativeWrapped_", "type": "address" } ], - "name": "changeAdmin", - "outputs": [], "stateMutability": "nonpayable", - "type": "function" + "type": "constructor" }, { "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": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "availableBalance", - "type": "uint256" - } - ], - "name": "InsufficientBalance", + "name": "ApproveFailed", "type": "error" }, { "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "address", - "name": "user", - "type": "address" - }, { "internalType": "uint256", - "name": "owedAmount", + "name": "loopsLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "amount", + "name": "requiredLoops", "type": "uint256" } ], - "name": "InsufficientDebt", + "name": "MaxLoopsLimitExceeded", "type": "error" }, { @@ -30149,44 +30901,20 @@ "name": "comptroller", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - }, { "indexed": true, "internalType": "address", - "name": "highestBidder", + "name": "asset", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "highestBidBps", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "seizedRiskFind", + "name": "amount", "type": "uint256" - }, - { - "indexed": false, - "internalType": "contract VToken[]", - "name": "markets", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "marketDebt", - "type": "uint256[]" } ], - "name": "AuctionClosed", + "name": "AssetsReservesUpdated", "type": "event" }, { @@ -30195,123 +30923,30 @@ { "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "oldConvertibleBaseAsset", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - } - ], - "name": "AuctionRestarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ { "indexed": true, "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "enum Shortfall.AuctionType", - "name": "auctionType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "contract VToken[]", - "name": "markets", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "marketsDebt", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "seizedRiskFund", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startBidBps", - "type": "uint256" - } - ], - "name": "AuctionStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "AuctionsPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "sender", + "name": "newConvertibleBaseAsset", "type": "address" } ], - "name": "AuctionsResumed", + "name": "ConvertibleBaseAssetUpdated", "type": "event" }, { "anonymous": false, "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - }, { "indexed": false, - "internalType": "uint256", - "name": "bidBps", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "bidder", - "type": "address" + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "BidPlaced", + "name": "Initialized", "type": "event" }, { @@ -30320,30 +30955,17 @@ { "indexed": false, "internalType": "uint256", - "name": "oldIncentiveBps", + "name": "oldMaxLoopsLimit", "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "newIncentiveBps", + "name": "newmaxLoopsLimit", "type": "uint256" } ], - "name": "IncentiveBpsUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", + "name": "MaxLoopsLimitUpdated", "type": "event" }, { @@ -30352,17 +30974,17 @@ { "indexed": false, "internalType": "uint256", - "name": "oldMinimumPoolBadDebt", + "name": "oldMinAmountToConvert", "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "newMinimumPoolBadDebt", + "name": "newMinAmountToConvert", "type": "uint256" } ], - "name": "MinimumPoolBadDebtUpdated", + "name": "MinAmountToConvertUpdated", "type": "event" }, { @@ -30388,19 +31010,19 @@ "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "oldNextBidderBlockLimit", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "newNextBidderBlockLimit", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "NextBidderBlockLimitUpdated", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -30419,7 +31041,7 @@ "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "OwnershipTransferred", "type": "event" }, { @@ -30428,17 +31050,17 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "oldPancakeSwapRouter", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "newPancakeSwapRouter", "type": "address" } ], - "name": "OwnershipTransferred", + "name": "PancakeSwapRouterUpdated", "type": "event" }, { @@ -30466,23 +31088,42 @@ { "indexed": true, "internalType": "address", - "name": "token", + "name": "oldShortfallContract", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "user", + "name": "newShortfallContract", "type": "address" + } + ], + "name": "ShortfallContractUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "amountsOutMin", + "type": "uint256[]" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "totalAmount", "type": "uint256" } ], - "name": "TokenDebtAdded", + "name": "SwappedPoolsAssets", "type": "event" }, { @@ -30497,7 +31138,7 @@ { "indexed": true, "internalType": "address", - "name": "user", + "name": "to", "type": "address" }, { @@ -30507,28 +31148,67 @@ "type": "uint256" } ], - "name": "TokenDebtClaimed", + "name": "SweepToken", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "oldWaitForFirstBidder", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "newWaitForFirstBidder", + "name": "amount", "type": "uint256" } ], - "name": "WaitForFirstBidderUpdated", + "name": "TransferredReserveForAuction", "type": "event" }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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", @@ -30557,46 +31237,11 @@ "type": "address" } ], - "name": "auctions", + "name": "assetsReserves", "outputs": [ { "internalType": "uint256", - "name": "startBlock", - "type": "uint256" - }, - { - "internalType": "enum Shortfall.AuctionType", - "name": "auctionType", - "type": "uint8" - }, - { - "internalType": "enum Shortfall.AuctionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "seizedRiskFund", - "type": "uint256" - }, - { - "internalType": "address", - "name": "highestBidder", - "type": "address" - }, - { - "internalType": "uint256", - "name": "highestBidBps", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "highestBidBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "startBidBps", + "name": "", "type": "uint256" } ], @@ -30605,12 +31250,12 @@ }, { "inputs": [], - "name": "auctionsPaused", + "name": "convertibleBaseAsset", "outputs": [ { - "internalType": "bool", + "internalType": "address", "name": "", - "type": "bool" + "type": "address" } ], "stateMutability": "view", @@ -30619,19 +31264,25 @@ { "inputs": [ { - "internalType": "contract IERC20Upgradeable", - "name": "token", + "internalType": "address", + "name": "comptroller", "type": "address" }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPoolAssetReserve", + "outputs": [ { "internalType": "uint256", - "name": "amount_", + "name": "", "type": "uint256" } ], - "name": "claimTokenDebt", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -30642,14 +31293,7 @@ "type": "address" } ], - "name": "closeAuction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "incentiveBps", + "name": "getPoolsBaseAssetReserves", "outputs": [ { "internalType": "uint256", @@ -30663,19 +31307,29 @@ { "inputs": [ { - "internalType": "contract IRiskFund", - "name": "riskFund_", + "internalType": "address", + "name": "pancakeSwapRouter_", "type": "address" }, { "internalType": "uint256", - "name": "minimumPoolBadDebt_", + "name": "minAmountToConvert_", "type": "uint256" }, + { + "internalType": "address", + "name": "convertibleBaseAsset_", + "type": "address" + }, { "internalType": "address", "name": "accessControlManager_", "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" } ], "name": "initialize", @@ -30685,7 +31339,7 @@ }, { "inputs": [], - "name": "minimumPoolBadDebt", + "name": "maxLoopsLimit", "outputs": [ { "internalType": "uint256", @@ -30698,7 +31352,7 @@ }, { "inputs": [], - "name": "nextBidderBlockLimit", + "name": "minAmountToConvert", "outputs": [ { "internalType": "uint256", @@ -30724,14 +31378,7 @@ }, { "inputs": [], - "name": "pauseAuctions", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", + "name": "pancakeSwapRouter", "outputs": [ { "internalType": "address", @@ -30743,26 +31390,16 @@ "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "pendingOwner", + "outputs": [ { "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" - }, - { - "internalType": "uint256", - "name": "bidBps", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" } ], - "name": "placeBid", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -30789,44 +31426,50 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "accessControlManager_", "type": "address" } ], - "name": "restartAuction", + "name": "setAccessControlManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "resumeAuctions", + "inputs": [ + { + "internalType": "address", + "name": "_convertibleBaseAsset", + "type": "address" + } + ], + "name": "setConvertibleBaseAsset", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "riskFund", - "outputs": [ + "inputs": [ { - "internalType": "contract IRiskFund", - "name": "", - "type": "address" + "internalType": "uint256", + "name": "limit", + "type": "uint256" } ], - "stateMutability": "view", + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "accessControlManager_", - "type": "address" + "internalType": "uint256", + "name": "minAmountToConvert_", + "type": "uint256" } ], - "name": "setAccessControlManager", + "name": "setMinAmountToConvert", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -30835,11 +31478,11 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "pancakeSwapRouter_", "type": "address" } ], - "name": "startAuction", + "name": "setPancakeSwapRouter", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -30847,22 +31490,37 @@ { "inputs": [ { - "internalType": "contract IERC20Upgradeable", - "name": "", + "internalType": "address", + "name": "poolRegistry_", "type": "address" - }, + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "", + "name": "shortfallContractAddress_", "type": "address" } ], - "name": "tokenDebt", + "name": "setShortfallContractAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -30871,12 +31529,27 @@ { "inputs": [ { - "internalType": "contract IERC20Upgradeable", - "name": "", - "type": "address" + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amountsOutMin", + "type": "uint256[]" + }, + { + "internalType": "address[][]", + "name": "paths", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "totalTokenDebt", + "name": "swapPoolsAssets", "outputs": [ { "internalType": "uint256", @@ -30884,18 +31557,23 @@ "type": "uint256" } ], - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "newOwner", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", "type": "address" } ], - "name": "transferOwnership", + "name": "sweepToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -30903,39 +31581,37 @@ { "inputs": [ { - "internalType": "uint256", - "name": "_incentiveBps", - "type": "uint256" + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "updateIncentiveBps", + "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, { "internalType": "uint256", - "name": "_minimumPoolBadDebt", + "name": "amount", "type": "uint256" } ], - "name": "updateMinimumPoolBadDebt", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "name": "transferReserveForAuction", + "outputs": [ { "internalType": "uint256", - "name": "_nextBidderBlockLimit", + "name": "", "type": "uint256" } ], - "name": "updateNextBidderBlockLimit", - "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -30943,41 +31619,25 @@ "inputs": [ { "internalType": "address", - "name": "poolRegistry_", + "name": "comptroller", "type": "address" - } - ], - "name": "updatePoolRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, { - "internalType": "uint256", - "name": "_waitForFirstBidder", - "type": "uint256" + "internalType": "address", + "name": "asset", + "type": "address" } ], - "name": "updateWaitForFirstBidder", + "name": "updateAssetsState", "outputs": [], "stateMutability": "nonpayable", "type": "function" - }, - { - "inputs": [], - "name": "waitForFirstBidder", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, + } + ] + }, + "RiskFund_Proxy": { + "address": "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42", + "abi": [ { "inputs": [ { @@ -30998,142 +31658,152 @@ ], "stateMutability": "payable", "type": "constructor" - } - ] - }, - "Shortfall_Implementation": { - "address": "0x916e607AF3250ECB2Fd4ea82A37Eb2756A20e1fC", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "token", + "name": "previousAdmin", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "recipient", + "name": "newAdmin", "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "availableBalance", - "type": "uint256" } ], - "name": "InsufficientBalance", - "type": "error" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "token", + "name": "beacon", "type": "address" - }, + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "user", + "name": "implementation", "type": "address" - }, - { - "internalType": "uint256", - "name": "owedAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "InsufficientDebt", - "type": "error" + "name": "Upgraded", + "type": "event" }, { - "inputs": [ + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ { "internalType": "address", - "name": "sender", + "name": "admin_", "type": "address" - }, + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "calledContract", + "name": "newAdmin", "type": "address" - }, - { - "internalType": "string", - "name": "methodSignature", - "type": "string" } ], - "name": "Unauthorized", - "type": "error" + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "newImplementation", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - }, + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "indexed": true, "internalType": "address", - "name": "highestBidder", + "name": "newImplementation", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "highestBidBps", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "seizedRiskFind", - "type": "uint256" - }, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "Shortfall": { + "address": "0xf37530A8a810Fcb501AA0Ecd0B0699388F0F2209", + "abi": [ + { + "anonymous": false, + "inputs": [ { "indexed": false, - "internalType": "contract VToken[]", - "name": "markets", - "type": "address[]" + "internalType": "address", + "name": "previousAdmin", + "type": "address" }, { "indexed": false, - "internalType": "uint256[]", - "name": "marketDebt", - "type": "uint256[]" + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "name": "AuctionClosed", + "name": "AdminChanged", "type": "event" }, { @@ -31142,17 +31812,248 @@ { "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "beacon", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" } ], - "name": "AuctionRestarted", + "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": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "availableBalance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "owedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "InsufficientDebt", + "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": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "highestBidder", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "highestBidBps", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizedRiskFind", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract VToken[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "marketDebt", + "type": "uint256[]" + } + ], + "name": "AuctionClosed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" + } + ], + "name": "AuctionRestarted", "type": "event" }, { @@ -31924,12 +32825,7 @@ ], "stateMutability": "view", "type": "function" - } - ] - }, - "Shortfall_Proxy": { - "address": "0xf37530A8a810Fcb501AA0Ecd0B0699388F0F2209", - "abi": [ + }, { "inputs": [ { @@ -31950,391 +32846,357 @@ ], "stateMutability": "payable", "type": "constructor" + } + ] + }, + "Shortfall_Implementation": { + "address": "0x916e607AF3250ECB2Fd4ea82A37Eb2756A20e1fC", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "token", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "recipient", "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "availableBalance", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "InsufficientBalance", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "user", "type": "address" + }, + { + "internalType": "uint256", + "name": "owedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "InsufficientDebt", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "name": "Upgraded", - "type": "event" + "name": "Unauthorized", + "type": "error" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" }, { - "inputs": [], - "name": "admin", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "admin_", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "highestBidder", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "highestBidBps", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizedRiskFind", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract VToken[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "marketDebt", + "type": "uint256[]" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "AuctionClosed", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newAdmin", + "name": "comptroller", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" } ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AuctionRestarted", + "type": "event" }, { - "inputs": [], - "name": "implementation", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "implementation_", + "name": "comptroller", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum Shortfall.AuctionType", + "name": "auctionType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "contract VToken[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "marketsDebt", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizedRiskFund", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startBidBps", + "type": "uint256" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "AuctionStarted", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "newImplementation", + "name": "sender", "type": "address" } ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AuctionsPaused", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "newImplementation", + "name": "sender", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" + "name": "AuctionsResumed", + "type": "event" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "SwapRouter_DeFi": { - "address": "0x47bEe99BD8Cf5D8d7e815e2D2a3E2985CBCcC04b", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "WBNB_", + "name": "comptroller", "type": "address" }, { - "internalType": "address", - "name": "factory_", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" }, { - "internalType": "address", - "name": "_comptrollerAddress", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "bidBps", + "type": "uint256" }, { + "indexed": true, "internalType": "address", - "name": "_vBNBAddress", + "name": "bidder", "type": "address" } ], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "BidPlaced", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "oldIncentiveBps", "type": "uint256" }, { + "indexed": false, "internalType": "uint256", - "name": "amountMax", + "name": "newIncentiveBps", "type": "uint256" } ], - "name": "ExcessiveInputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "IdenticalAddresses", - "type": "error" + "name": "IncentiveBpsUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountIntMax", - "type": "uint256" - } - ], - "name": "InputAmountAboveMaximum", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "sweepAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientInputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientOutputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPath", - "type": "error" + "name": "Initialized", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", + "name": "oldMinimumPoolBadDebt", "type": "uint256" - } - ], - "name": "OutputAmountBelowMinimum", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCheck", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "repayer", - "type": "address" - }, - { - "internalType": "address", - "name": "vToken", - "type": "address" }, { + "indexed": false, "internalType": "uint256", - "name": "errorCode", + "name": "newMinimumPoolBadDebt", "type": "uint256" } ], - "name": "RepayError", - "type": "error" - }, - { - "inputs": [], - "name": "SafeApproveFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferBNBFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferFromFailed", - "type": "error" + "name": "MinimumPoolBadDebtUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "supplier", + "name": "oldAccessControlManager", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "vToken", + "name": "newAccessControlManager", "type": "address" - }, - { - "internalType": "uint256", - "name": "errorCode", - "type": "uint256" - } - ], - "name": "SupplyError", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "swapAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" } ], - "name": "SwapAmountLessThanAmountOutMin", - "type": "error" + "name": "NewAccessControlManager", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "uint256", - "name": "deadline", + "name": "oldNextBidderBlockLimit", "type": "uint256" }, { + "indexed": false, "internalType": "uint256", - "name": "timestemp", + "name": "newNextBidderBlockLimit", "type": "uint256" } ], - "name": "SwapDeadlineExpire", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "VTokenNotListed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "underlying", - "type": "address" - } - ], - "name": "VTokenUnderlyingInvalid", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "expectedAdddress", - "type": "address" - }, - { - "internalType": "address", - "name": "passedAddress", - "type": "address" - } - ], - "name": "WrongAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" + "name": "NextBidderBlockLimitUpdated", + "type": "event" }, { "anonymous": false, @@ -32380,86 +33242,17 @@ { "indexed": true, "internalType": "address", - "name": "swapper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "name": "SwapBnbForTokens", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "swapper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "SwapBnbForTokensAtSupportingFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "swapper", + "name": "oldPoolRegistry", "type": "address" }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "name": "SwapTokensForBnb", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ { "indexed": true, "internalType": "address", - "name": "swapper", + "name": "newPoolRegistry", "type": "address" - }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" } ], - "name": "SwapTokensForBnbAtSupportingFee", + "name": "PoolRegistryUpdated", "type": "event" }, { @@ -32468,42 +33261,23 @@ { "indexed": true, "internalType": "address", - "name": "swapper", + "name": "token", "type": "address" }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "name": "SwapTokensForTokens", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ { "indexed": true, "internalType": "address", - "name": "swapper", + "name": "user", "type": "address" }, { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "SwapTokensForTokensAtSupportingFee", + "name": "TokenDebtAdded", "type": "event" }, { @@ -32518,51 +33292,38 @@ { "indexed": true, "internalType": "address", - "name": "to", + "name": "user", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "sweepAmount", + "name": "amount", "type": "uint256" } ], - "name": "SweepToken", + "name": "TokenDebtClaimed", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "oldAddress", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "oldWaitForFirstBidder", + "type": "uint256" }, { - "indexed": true, - "internalType": "address", - "name": "newAddress", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "newWaitForFirstBidder", + "type": "uint256" } ], - "name": "VBNBAddressUpdated", + "name": "WaitForFirstBidderUpdated", "type": "event" }, - { - "inputs": [], - "name": "WBNB", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "acceptOwnership", @@ -32572,10 +33333,10 @@ }, { "inputs": [], - "name": "comptrollerAddress", + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -32584,119 +33345,160 @@ "type": "function" }, { - "inputs": [], - "name": "factory", - "outputs": [ + "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ + "name": "auctions", + "outputs": [ { "internalType": "uint256", - "name": "amountOut", + "name": "startBlock", "type": "uint256" }, + { + "internalType": "enum Shortfall.AuctionType", + "name": "auctionType", + "type": "uint8" + }, + { + "internalType": "enum Shortfall.AuctionStatus", + "name": "status", + "type": "uint8" + }, { "internalType": "uint256", - "name": "reserveIn", + "name": "seizedRiskFund", + "type": "uint256" + }, + { + "internalType": "address", + "name": "highestBidder", + "type": "address" + }, + { + "internalType": "uint256", + "name": "highestBidBps", "type": "uint256" }, { "internalType": "uint256", - "name": "reserveOut", + "name": "highestBidBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startBidBps", "type": "uint256" } ], - "name": "getAmountIn", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "auctionsPaused", "outputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" + "internalType": "bool", + "name": "", + "type": "bool" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" }, { "internalType": "uint256", - "name": "reserveIn", + "name": "amount_", "type": "uint256" - }, + } + ], + "name": "claimTokenDebt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "internalType": "uint256", - "name": "reserveOut", - "type": "uint256" + "internalType": "address", + "name": "comptroller", + "type": "address" } ], - "name": "getAmountOut", + "name": "closeAuction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "incentiveBps", "outputs": [ { "internalType": "uint256", - "name": "amountOut", + "name": "", "type": "uint256" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { "inputs": [ + { + "internalType": "contract IRiskFund", + "name": "riskFund_", + "type": "address" + }, { "internalType": "uint256", - "name": "amountOut", + "name": "minimumPoolBadDebt_", "type": "uint256" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "accessControlManager_", + "type": "address" } ], - "name": "getAmountsIn", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minimumPoolBadDebt", "outputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "nextBidderBlockLimit", + "outputs": [ { "internalType": "uint256", - "name": "amountIn", + "name": "", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "getAmountsOut", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" } ], "stateMutability": "view", @@ -32715,6 +33517,13 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "pauseAuctions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "pendingOwner", @@ -32731,379 +33540,348 @@ { "inputs": [ { - "internalType": "uint256", - "name": "amountA", - "type": "uint256" + "internalType": "address", + "name": "comptroller", + "type": "address" }, { "internalType": "uint256", - "name": "reserveA", + "name": "bidBps", "type": "uint256" }, { "internalType": "uint256", - "name": "reserveB", - "type": "uint256" - } - ], - "name": "quote", - "outputs": [ - { - "internalType": "uint256", - "name": "amountB", + "name": "auctionStartBlock", "type": "uint256" } ], - "stateMutability": "pure", + "name": "placeBid", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "name": "poolRegistry", + "outputs": [ { "internalType": "address", - "name": "_vBNBAddress", + "name": "", "type": "address" } ], - "name": "setVBNBAddress", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "address", - "name": "to", + "name": "comptroller", "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapBNBForExactTokens", + "name": "restartAuction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resumeAuctions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "riskFund", "outputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "contract IRiskFund", + "name": "", + "type": "address" } ], - "stateMutability": "payable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "accessControlManager_", "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapBNBForExactTokensAndRepay", + "name": "setAccessControlManager", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "comptroller", "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapBNBForExactTokensAndSupply", + "name": "startAuction", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "vTokenAddress", + "internalType": "contract IERC20Upgradeable", + "name": "", "type": "address" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenDebt", + "outputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "", "type": "uint256" } ], - "name": "swapBNBForFullTokenDebtAndRepay", - "outputs": [], - "stateMutability": "payable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", + "internalType": "contract IERC20Upgradeable", + "name": "", "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapExactBNBForTokens", + "name": "totalTokenDebt", "outputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "stateMutability": "payable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "newOwner", "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "_incentiveBps", "type": "uint256" } ], - "name": "swapExactBNBForTokensAndRepay", + "name": "updateIncentiveBps", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, { "internalType": "uint256", - "name": "amountOutMin", + "name": "_minimumPoolBadDebt", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + } + ], + "name": "updateMinimumPoolBadDebt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "_nextBidderBlockLimit", "type": "uint256" } ], - "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "name": "updateNextBidderBlockLimit", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "poolRegistry_", "type": "address" - }, + } + ], + "name": "updatePoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "amountOutMin", + "name": "_waitForFirstBidder", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + } + ], + "name": "updateWaitForFirstBidder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "waitForFirstBidder", + "outputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "", "type": "uint256" } ], - "name": "swapExactBNBForTokensAndSupply", - "outputs": [], - "stateMutability": "payable", + "stateMutability": "view", "type": "function" - }, + } + ] + }, + "Shortfall_Proxy": { + "address": "0xf37530A8a810Fcb501AA0Ecd0B0699388F0F2209", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "_logic", "type": "address" }, { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "admin_", + "type": "address" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", - "outputs": [], "stateMutability": "payable", - "type": "function" + "type": "constructor" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "to", + "name": "beacon", "type": "address" - }, + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" } ], - "name": "swapExactBNBForTokensAtSupportingFee", + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", "outputs": [ { - "internalType": "uint256", - "name": "swapAmount", - "type": "uint256" + "internalType": "address", + "name": "admin_", + "type": "address" } ], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "address", - "name": "to", + "name": "newAdmin", "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapExactTokensForBNB", + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", "outputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "address", + "name": "implementation_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -33112,27 +33890,12 @@ { "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "address", + "name": "newImplementation", + "type": "address" } ], - "name": "swapExactTokensForBNBAndRepay", + "name": "upgradeTo", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -33140,86 +33903,76 @@ { "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "newImplementation", + "type": "address" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "swapExactTokensForBNBAndRepayAtSupportingFee", + "name": "upgradeToAndCall", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "SwapRouter_DeFi": { + "address": "0x47bEe99BD8Cf5D8d7e815e2D2a3E2985CBCcC04b", + "abi": [ { "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" + "internalType": "address", + "name": "WBNB_", + "type": "address" }, { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" + "internalType": "address", + "name": "factory_", + "type": "address" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "_comptrollerAddress", + "type": "address" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" } ], - "name": "swapExactTokensForBNBAndSupply", - "outputs": [], "stateMutability": "nonpayable", - "type": "function" + "type": "constructor" }, { "inputs": [ { "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", + "name": "amount", "type": "uint256" }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "uint256", - "name": "deadline", + "name": "amountMax", "type": "uint256" } ], - "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "ExcessiveInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" }, { "inputs": [ @@ -33230,536 +33983,457 @@ }, { "internalType": "uint256", - "name": "amountOutMin", + "name": "amountIntMax", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, + } + ], + "name": "InputAmountAboveMaximum", + "type": "error" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "sweepAmount", "type": "uint256" - } - ], - "name": "swapExactTokensForBNBAtSupportingFee", - "outputs": [ + }, { "internalType": "uint256", - "name": "swapAmount", + "name": "balance", "type": "uint256" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientOutputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPath", + "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "amountIn", + "name": "amountOut", "type": "uint256" }, { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactTokensForTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "OutputAmountBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCheck", + "type": "error" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "repayer", "type": "address" }, { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "vToken", + "type": "address" }, { "internalType": "uint256", - "name": "deadline", + "name": "errorCode", "type": "uint256" } ], - "name": "swapExactTokensForTokensAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "RepayError", + "type": "error" + }, + { + "inputs": [], + "name": "SafeApproveFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferBNBFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFromFailed", + "type": "error" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "supplier", "type": "address" }, { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "vToken", + "type": "address" }, { "internalType": "uint256", - "name": "deadline", + "name": "errorCode", "type": "uint256" } ], - "name": "swapExactTokensForTokensAndRepayAtSupportingFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SupplyError", + "type": "error" }, { "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, { "internalType": "uint256", - "name": "amountIn", + "name": "swapAmount", "type": "uint256" }, { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapExactTokensForTokensAndSupply", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" }, { "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, { "internalType": "uint256", - "name": "amountOutMin", + "name": "deadline", "type": "uint256" }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "uint256", - "name": "deadline", + "name": "timestemp", "type": "uint256" } ], - "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapDeadlineExpire", + "type": "error" }, { "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "address", - "name": "to", + "name": "vToken", "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapExactTokensForTokensAtSupportingFee", - "outputs": [ + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ { - "internalType": "uint256", - "name": "swapAmount", - "type": "uint256" + "internalType": "address", + "name": "underlying", + "type": "address" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "VTokenUnderlyingInvalid", + "type": "error" }, { "inputs": [ { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "internalType": "address", + "name": "expectedAdddress", + "type": "address" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + "internalType": "address", + "name": "passedAddress", + "type": "address" + } + ], + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "to", + "name": "previousOwner", "type": "address" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "swapTokensForExactBNB", - "outputs": [ + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "OwnershipTransferred", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" }, { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "swapTokensForExactBNBAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapBnbForTokens", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" }, { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapTokensForExactBNBAndSupply", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapBnbForTokensAtSupportingFee", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" }, { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" }, { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapTokensForExactTokens", - "outputs": [ - { + "indexed": true, "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapTokensForBnb", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "vTokenAddress", + "name": "swapper", "type": "address" }, { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" - }, - { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapTokensForExactTokensAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapTokensForBnbAtSupportingFee", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "vTokenAddress", + "name": "swapper", "type": "address" }, { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" - }, - { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "swapTokensForExactTokensAndSupply", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapTokensForTokens", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" }, { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapTokensForFullBNBDebtAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapTokensForTokensAtSupportingFee", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "vTokenAddress", + "name": "token", "type": "address" }, { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" }, { + "indexed": false, "internalType": "uint256", - "name": "deadline", + "name": "sweepAmount", "type": "uint256" } ], - "name": "swapTokensForFullTokenDebtAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SweepToken", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "contract IERC20", - "name": "token", + "indexed": true, + "internalType": "address", + "name": "oldAddress", "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "to", + "name": "newAddress", "type": "address" - }, + } + ], + "name": "VBNBAddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ { - "internalType": "uint256", - "name": "sweepAmount", - "type": "uint256" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "sweepToken", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ { "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "vBNBAddress", + "name": "factory", "outputs": [ { "internalType": "address", @@ -33770,61 +34444,34 @@ "stateMutability": "view", "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "SwapRouter_GameFi": { - "address": "0x9B15462a79D0948BdDF679E0E5a9841C44aAFB7A", - "abi": [ { "inputs": [ { - "internalType": "address", - "name": "WBNB_", - "type": "address" - }, - { - "internalType": "address", - "name": "factory_", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" }, { - "internalType": "address", - "name": "_comptrollerAddress", - "type": "address" + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" }, - { - "internalType": "address", - "name": "_vBNBAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ { "internalType": "uint256", - "name": "amount", + "name": "reserveOut", "type": "uint256" - }, + } + ], + "name": "getAmountIn", + "outputs": [ { "internalType": "uint256", - "name": "amountMax", + "name": "amountIn", "type": "uint256" } ], - "name": "ExcessiveInputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "IdenticalAddresses", - "type": "error" + "stateMutability": "pure", + "type": "function" }, { "inputs": [ @@ -33835,48 +34482,25 @@ }, { "internalType": "uint256", - "name": "amountIntMax", + "name": "reserveIn", "type": "uint256" - } - ], - "name": "InputAmountAboveMaximum", - "type": "error" - }, - { - "inputs": [ + }, { "internalType": "uint256", - "name": "sweepAmount", + "name": "reserveOut", "type": "uint256" - }, + } + ], + "name": "getAmountOut", + "outputs": [ { "internalType": "uint256", - "name": "balance", + "name": "amountOut", "type": "uint256" } ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientInputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientOutputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPath", - "type": "error" + "stateMutability": "pure", + "type": "function" }, { "inputs": [ @@ -33886,888 +34510,412 @@ "type": "uint256" }, { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "OutputAmountBelowMinimum", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCheck", - "type": "error" + "name": "getAmountsIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "repayer", - "type": "address" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" }, { - "internalType": "address", - "name": "vToken", - "type": "address" - }, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsOut", + "outputs": [ { - "internalType": "uint256", - "name": "errorCode", - "type": "uint256" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "RepayError", - "type": "error" - }, - { - "inputs": [], - "name": "SafeApproveFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferBNBFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferFailed", - "type": "error" + "stateMutability": "view", + "type": "function" }, { "inputs": [], - "name": "SafeTransferFromFailed", - "type": "error" - }, - { - "inputs": [ + "name": "owner", + "outputs": [ { "internalType": "address", - "name": "supplier", + "name": "", "type": "address" - }, + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ { "internalType": "address", - "name": "vToken", + "name": "", "type": "address" - }, - { - "internalType": "uint256", - "name": "errorCode", - "type": "uint256" } ], - "name": "SupplyError", - "type": "error" + "stateMutability": "view", + "type": "function" }, { "inputs": [ { "internalType": "uint256", - "name": "swapAmount", + "name": "amountA", "type": "uint256" }, { "internalType": "uint256", - "name": "amountOutMin", + "name": "reserveA", "type": "uint256" - } - ], - "name": "SwapAmountLessThanAmountOutMin", - "type": "error" - }, - { - "inputs": [ + }, { "internalType": "uint256", - "name": "deadline", + "name": "reserveB", "type": "uint256" - }, + } + ], + "name": "quote", + "outputs": [ { "internalType": "uint256", - "name": "timestemp", + "name": "amountB", "type": "uint256" } ], - "name": "SwapDeadlineExpire", - "type": "error" + "stateMutability": "pure", + "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "VTokenNotListed", - "type": "error" + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "underlying", + "name": "_vBNBAddress", "type": "address" } ], - "name": "VTokenUnderlyingInvalid", - "type": "error" + "name": "setVBNBAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "expectedAdddress", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" }, { - "internalType": "address", - "name": "passedAddress", - "type": "address" - } - ], - "name": "WrongAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "to", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "name": "swapBNBForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "OwnershipTransferred", - "type": "event" + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapBnbForTokens", - "type": "event" + "name": "swapBNBForExactTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapBnbForTokensAtSupportingFee", - "type": "event" + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "swapper", - "type": "address" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" }, { - "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" }, { - "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokens", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } ], - "name": "SwapTokensForBnb", - "type": "event" + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { "internalType": "address[]", "name": "path", "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapTokensForBnbAtSupportingFee", - "type": "event" + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapTokensForTokens", - "type": "event" + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { "internalType": "address[]", "name": "path", "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapTokensForTokensAtSupportingFee", - "type": "event" + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "token", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": false, "internalType": "uint256", - "name": "sweepAmount", + "name": "deadline", "type": "uint256" } ], - "name": "SweepToken", - "type": "event" + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "oldAddress", - "type": "address" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": true, "internalType": "address", - "name": "newAddress", + "name": "to", "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "VBNBAddressUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "WBNB", + "name": "swapExactBNBForTokensAtSupportingFee", "outputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "comptrollerAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "factory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveOut", - "type": "uint256" - } - ], - "name": "getAmountIn", - "outputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveOut", - "type": "uint256" - } - ], - "name": "getAmountOut", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "getAmountsIn", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "getAmountsOut", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "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": "uint256", - "name": "amountA", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveA", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveB", - "type": "uint256" - } - ], - "name": "quote", - "outputs": [ - { - "internalType": "uint256", - "name": "amountB", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vBNBAddress", - "type": "address" - } - ], - "name": "setVBNBAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapBNBForExactTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapBNBForExactTokensAndRepay", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapBNBForExactTokensAndSupply", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapBNBForFullTokenDebtAndRepay", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAndRepay", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAndRepayAtSupportingFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAndSupply", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAtSupportingFee", - "outputs": [ - { - "internalType": "uint256", - "name": "swapAmount", - "type": "uint256" - } - ], - "stateMutability": "payable", + "stateMutability": "payable", "type": "function" }, { @@ -35476,8 +35624,8 @@ } ] }, - "SwapRouter_LiquidStakedBNB": { - "address": "0x5f0ce69Aa564468492e860e8083BB001e4eb8d56", + "SwapRouter_GameFi": { + "address": "0x9B15462a79D0948BdDF679E0E5a9841C44aAFB7A", "abi": [ { "inputs": [ @@ -37176,8 +37324,8 @@ } ] }, - "SwapRouter_Stablecoins": { - "address": "0xBBd8E2b5d69fcE9Aaa599c50F0f0960AA58B32aA", + "SwapRouter_LiquidStakedBNB": { + "address": "0x5f0ce69Aa564468492e860e8083BB001e4eb8d56", "abi": [ { "inputs": [ @@ -38876,8 +39024,8 @@ } ] }, - "SwapRouter_Tron": { - "address": "0xacD270Ed7DFd4466Bd931d84fe5B904080E28Bfc", + "SwapRouter_Stablecoins": { + "address": "0xBBd8E2b5d69fcE9Aaa599c50F0f0960AA58B32aA", "abi": [ { "inputs": [ @@ -40576,383 +40724,283 @@ } ] }, - "VTokenBeacon": { - "address": "0x2b8A1C539ABaC89CbF7E2Bc6987A0A38A5e660D4", + "SwapRouter_Tron": { + "address": "0xacD270Ed7DFd4466Bd931d84fe5B904080E28Bfc", "abi": [ { "inputs": [ { "internalType": "address", - "name": "implementation_", + "name": "WBNB_", "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "factory_", "type": "address" }, { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "_comptrollerAddress", "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "_vBNBAddress", "type": "address" } ], - "name": "Upgraded", - "type": "event" + "stateMutability": "nonpayable", + "type": "constructor" }, { - "inputs": [], - "name": "implementation", - "outputs": [ + "inputs": [ { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, { - "internalType": "address", - "name": "", - "type": "address" + "internalType": "uint256", + "name": "amountMax", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "ExcessiveInputAmount", + "type": "error" }, { "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "IdenticalAddresses", + "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, { - "internalType": "address", - "name": "newImplementation", - "type": "address" + "internalType": "uint256", + "name": "amountIntMax", + "type": "uint256" } ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "VTokenImpl": { - "address": "0x3E4F3F90fD01766472E654748509C6eD81e7C62c", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "InputAmountAboveMaximum", + "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "actualAddAmount", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", "type": "uint256" } ], - "name": "AddReservesFactorFreshCheck", + "name": "InsufficientBalance", "type": "error" }, { "inputs": [], - "name": "BorrowCashNotAvailable", + "name": "InsufficientInputAmount", "type": "error" }, { "inputs": [], - "name": "BorrowFreshnessCheck", + "name": "InsufficientLiquidity", "type": "error" }, { "inputs": [], - "name": "ForceLiquidateBorrowUnauthorized", + "name": "InsufficientOutputAmount", "type": "error" }, { "inputs": [], - "name": "HealBorrowUnauthorized", + "name": "InvalidPath", "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "errorCode", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", "type": "uint256" } ], - "name": "LiquidateAccrueCollateralInterestFailed", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateCloseAmountIsUintMax", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateCloseAmountIsZero", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateCollateralFreshnessCheck", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateFreshnessCheck", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateLiquidatorIsBorrower", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateSeizeLiquidatorIsBorrower", - "type": "error" - }, - { - "inputs": [], - "name": "MintFreshnessCheck", - "type": "error" - }, - { - "inputs": [], - "name": "ProtocolSeizeShareTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "RedeemFreshnessCheck", - "type": "error" - }, - { - "inputs": [], - "name": "RedeemTransferOutNotPossible", - "type": "error" - }, - { - "inputs": [], - "name": "ReduceReservesCashNotAvailable", - "type": "error" - }, - { - "inputs": [], - "name": "ReduceReservesCashValidation", + "name": "OutputAmountBelowMinimum", "type": "error" }, { "inputs": [], - "name": "ReduceReservesFreshCheck", + "name": "ReentrantCheck", "type": "error" }, { - "inputs": [], - "name": "RepayBorrowFreshnessCheck", + "inputs": [ + { + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RepayError", "type": "error" }, { "inputs": [], - "name": "SetInterestRateModelFreshCheck", + "name": "SafeApproveFailed", "type": "error" }, { "inputs": [], - "name": "SetReserveFactorBoundsCheck", + "name": "SafeTransferBNBFailed", "type": "error" }, { "inputs": [], - "name": "SetReserveFactorFreshCheck", + "name": "SafeTransferFailed", "type": "error" }, { "inputs": [], - "name": "TransferNotAllowed", + "name": "SafeTransferFromFailed", "type": "error" }, { "inputs": [ { "internalType": "address", - "name": "sender", + "name": "supplier", "type": "address" }, { "internalType": "address", - "name": "calledContract", + "name": "vToken", "type": "address" }, { - "internalType": "string", - "name": "methodSignature", - "type": "string" + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" } ], - "name": "Unauthorized", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", + "name": "SupplyError", "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "uint256", - "name": "cashPrior", + "name": "swapAmount", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "interestAccumulated", + "name": "amountOutMin", "type": "uint256" - }, + } + ], + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" + }, + { + "inputs": [ { - "indexed": false, "internalType": "uint256", - "name": "borrowIndex", + "name": "deadline", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "totalBorrows", + "name": "timestemp", "type": "uint256" } ], - "name": "AccrueInterest", - "type": "event" + "name": "SwapDeadlineExpire", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "owner", + "name": "vToken", "type": "address" - }, + } + ], + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ { - "indexed": true, "internalType": "address", - "name": "spender", + "name": "underlying", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "Approval", - "type": "event" + "name": "VTokenUnderlyingInvalid", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "borrower", + "name": "expectedAdddress", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "badDebtDelta", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "badDebtOld", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "badDebtNew", - "type": "uint256" + "internalType": "address", + "name": "passedAddress", + "type": "address" } ], - "name": "BadDebtIncreased", - "type": "event" + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "badDebtOld", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "badDebtNew", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "BadDebtRecovered", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -40961,29 +41009,17 @@ { "indexed": true, "internalType": "address", - "name": "borrower", + "name": "previousOwner", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "borrowAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "accountBorrows", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalBorrows", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "Borrow", + "name": "OwnershipTransferred", "type": "event" }, { @@ -40992,36 +41028,42 @@ { "indexed": true, "internalType": "address", - "name": "payer", + "name": "swapper", "type": "address" }, { "indexed": true, - "internalType": "address", - "name": "borrower", - "type": "address" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": false, - "internalType": "uint256", - "name": "repayAmount", - "type": "uint256" + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "HealBorrow", + "name": "SwapBnbForTokens", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "Initialized", + "name": "SwapBnbForTokensAtSupportingFee", "type": "event" }, { @@ -41030,35 +41072,42 @@ { "indexed": true, "internalType": "address", - "name": "liquidator", + "name": "swapper", "type": "address" }, { "indexed": true, - "internalType": "address", - "name": "borrower", - "type": "address" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": false, - "internalType": "uint256", - "name": "repayAmount", - "type": "uint256" - }, + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForBnb", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, "internalType": "address", - "name": "vTokenCollateral", + "name": "swapper", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "seizeTokens", - "type": "uint256" + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "LiquidateBorrow", + "name": "SwapTokensForBnbAtSupportingFee", "type": "event" }, { @@ -41067,48 +41116,42 @@ { "indexed": true, "internalType": "address", - "name": "minter", + "name": "swapper", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "mintAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "mintTokens", - "type": "uint256" + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": false, - "internalType": "uint256", - "name": "accountBalance", - "type": "uint256" + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "Mint", + "name": "SwapTokensForTokens", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "oldAccessControlManager", + "name": "swapper", "type": "address" }, { - "indexed": false, - "internalType": "address", - "name": "newAccessControlManager", - "type": "address" + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "NewAccessControlManager", + "name": "SwapTokensForTokensAtSupportingFee", "type": "event" }, { @@ -41116,18 +41159,24 @@ "inputs": [ { "indexed": true, - "internalType": "contract ComptrollerInterface", - "name": "oldComptroller", + "internalType": "address", + "name": "token", "type": "address" }, { "indexed": true, - "internalType": "contract ComptrollerInterface", - "name": "newComptroller", + "internalType": "address", + "name": "to", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" } ], - "name": "NewComptroller", + "name": "SweepToken", "type": "event" }, { @@ -41135,298 +41184,167 @@ "inputs": [ { "indexed": true, - "internalType": "contract InterestRateModel", - "name": "oldInterestRateModel", + "internalType": "address", + "name": "oldAddress", "type": "address" }, { "indexed": true, - "internalType": "contract InterestRateModel", - "name": "newInterestRateModel", + "internalType": "address", + "name": "newAddress", "type": "address" } ], - "name": "NewMarketInterestRateModel", + "name": "VBNBAddressUpdated", "type": "event" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldProtocolSeizeShareMantissa", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newProtocolSeizeShareMantissa", - "type": "uint256" - } - ], - "name": "NewProtocolSeizeShare", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "oldProtocolShareReserve", - "type": "address" - }, + "inputs": [], + "name": "WBNB", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "newProtocolShareReserve", + "name": "", "type": "address" } ], - "name": "NewProtocolShareReserve", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldReserveFactorMantissa", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newReserveFactorMantissa", - "type": "uint256" - } - ], - "name": "NewReserveFactor", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "oldShortfall", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newShortfall", - "type": "address" - } - ], - "name": "NewShortfallContract", - "type": "event" + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, + "inputs": [], + "name": "factory", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "OwnershipTransferred", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "redeemer", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "redeemAmount", + "name": "reserveIn", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "redeemTokens", + "name": "reserveOut", "type": "uint256" - }, + } + ], + "name": "getAmountIn", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "accountBalance", + "name": "amountIn", "type": "uint256" } ], - "name": "Redeem", - "type": "event" + "stateMutability": "pure", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "payer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "borrower", - "type": "address" - }, - { - "indexed": false, "internalType": "uint256", - "name": "repayAmount", + "name": "amountIn", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "accountBorrows", + "name": "reserveIn", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "totalBorrows", + "name": "reserveOut", "type": "uint256" } ], - "name": "RepayBorrow", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "benefactor", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "addAmount", - "type": "uint256" - }, + "name": "getAmountOut", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "newTotalReserves", + "name": "amountOut", "type": "uint256" } ], - "name": "ReservesAdded", - "type": "event" + "stateMutability": "pure", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, "internalType": "uint256", - "name": "reduceAmount", + "name": "amountOut", "type": "uint256" }, { - "indexed": false, - "internalType": "uint256", - "name": "newTotalReserves", - "type": "uint256" + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "ReservesReduced", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "getAmountsIn", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "SweepToken", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "amountIn", "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "NO_ERROR", + "name": "getAmountsOut", "outputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], "stateMutability": "view", @@ -41434,17 +41352,10 @@ }, { "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "accessControlManager", + "name": "owner", "outputs": [ { - "internalType": "contract IAccessControlManagerV8", + "internalType": "address", "name": "", "type": "address" } @@ -41454,39 +41365,62 @@ }, { "inputs": [], - "name": "accrualBlockNumber", + "name": "pendingOwner", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "accrueInterest", + "inputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "name": "quote", "outputs": [ { "internalType": "uint256", - "name": "", + "name": "amountB", "type": "uint256" } ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "uint256", - "name": "addAmount", - "type": "uint256" + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" } ], - "name": "addReserves", + "name": "setVBNBAddress", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -41494,396 +41428,520 @@ { "inputs": [ { - "internalType": "address", - "name": "owner", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { "internalType": "address", - "name": "spender", + "name": "to", "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "allowance", + "name": "swapBNBForExactTokens", "outputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "stateMutability": "view", + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "spender", + "name": "vTokenAddress", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountOut", "type": "uint256" - } - ], - "name": "approve", - "outputs": [ + }, { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "badDebt", - "outputs": [ + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, { "internalType": "uint256", - "name": "recoveredAmount_", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "name": "badDebtRecovered", + "name": "swapBNBForExactTokensAndSupply", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "owner", + "name": "vTokenAddress", "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "owner", + "name": "to", "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "balanceOfUnderlying", + "name": "swapExactBNBForTokens", "outputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, { "internalType": "uint256", - "name": "borrowAmount", + "name": "amountOutMin", "type": "uint256" - } - ], - "name": "borrow", - "outputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "nonpayable", + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "account", + "name": "vTokenAddress", "type": "address" - } - ], - "name": "borrowBalanceCurrent", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "nonpayable", + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "account", + "name": "vTokenAddress", "type": "address" - } - ], - "name": "borrowBalanceStored", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountOutMin", "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "borrowIndex", - "outputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { - "inputs": [], - "name": "borrowRatePerBlock", - "outputs": [ + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, { "internalType": "uint256", - "name": "", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { - "inputs": [], - "name": "comptroller", - "outputs": [ + "inputs": [ { - "internalType": "contract ComptrollerInterface", - "name": "", + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", + "name": "swapExactBNBForTokensAtSupportingFee", "outputs": [ { - "internalType": "uint8", - "name": "", - "type": "uint8" + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" } ], - "stateMutability": "view", + "stateMutability": "payable", "type": "function" }, { "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "spender", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "subtractedValue", + "name": "deadline", "type": "uint256" } ], - "name": "decreaseAllowance", + "name": "swapExactTokensForBNB", "outputs": [ { - "internalType": "bool", - "name": "", - "type": "bool" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "exchangeRateCurrent", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "amountIn", "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "exchangeRateStored", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactTokensForBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "liquidator", - "type": "address" - }, - { - "internalType": "address", - "name": "borrower", - "type": "address" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" }, { "internalType": "uint256", - "name": "repayAmount", + "name": "amountOutMin", "type": "uint256" }, { - "internalType": "contract VTokenInterface", - "name": "vTokenCollateral", - "type": "address" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "internalType": "bool", - "name": "skipLiquidityCheck", - "type": "bool" + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "forceLiquidateBorrow", + "name": "swapExactTokensForBNBAndRepayAtSupportingFee", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "getAccountSnapshot", - "outputs": [ { "internalType": "uint256", - "name": "error", + "name": "amountIn", "type": "uint256" }, { "internalType": "uint256", - "name": "vTokenBalance", + "name": "amountOutMin", "type": "uint256" }, { - "internalType": "uint256", - "name": "borrowBalance", - "type": "uint256" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { "internalType": "uint256", - "name": "exchangeRate", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactTokensForBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "getCash", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "payer", - "type": "address" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { "internalType": "address", - "name": "borrower", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "repayAmount", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", "type": "uint256" } ], - "name": "healBorrow", - "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "spender", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "addedValue", + "name": "deadline", "type": "uint256" } ], - "name": "increaseAllowance", + "name": "swapExactTokensForTokens", "outputs": [ { - "internalType": "bool", - "name": "", - "type": "bool" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], "stateMutability": "nonpayable", @@ -41893,129 +41951,131 @@ "inputs": [ { "internalType": "address", - "name": "underlying_", - "type": "address" - }, - { - "internalType": "contract ComptrollerInterface", - "name": "comptroller_", - "type": "address" - }, - { - "internalType": "contract InterestRateModel", - "name": "interestRateModel_", + "name": "vTokenAddress", "type": "address" }, { "internalType": "uint256", - "name": "initialExchangeRateMantissa_", + "name": "amountIn", "type": "uint256" }, { - "internalType": "string", - "name": "name_", - "type": "string" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" }, { - "internalType": "string", - "name": "symbol_", - "type": "string" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "internalType": "uint8", - "name": "decimals_", - "type": "uint8" - }, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "admin_", + "name": "vTokenAddress", "type": "address" }, { - "internalType": "address", - "name": "accessControlManager_", - "type": "address" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" }, { - "components": [ - { - "internalType": "address", - "name": "shortfall", - "type": "address" - }, - { - "internalType": "address payable", - "name": "protocolShareReserve", - "type": "address" - } - ], - "internalType": "struct VTokenInterface.RiskManagementInit", - "name": "riskManagement", - "type": "tuple" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { "internalType": "uint256", - "name": "reserveFactorMantissa_", + "name": "deadline", "type": "uint256" } ], - "name": "initialize", + "name": "swapExactTokensForTokensAndRepayAtSupportingFee", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "interestRateModel", - "outputs": [ + "inputs": [ { - "internalType": "contract InterestRateModel", - "name": "", + "internalType": "address", + "name": "vTokenAddress", "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isVToken", - "outputs": [ + }, { - "internalType": "bool", - "name": "", - "type": "bool" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "stateMutability": "pure", + "name": "swapExactTokensForTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "borrower", + "name": "vTokenAddress", "type": "address" }, { "internalType": "uint256", - "name": "repayAmount", + "name": "amountIn", "type": "uint256" }, { - "internalType": "contract VTokenInterface", - "name": "vTokenCollateral", - "type": "address" - } - ], - "name": "liquidateBorrow", - "outputs": [ + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], + "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -42023,39 +42083,35 @@ "inputs": [ { "internalType": "uint256", - "name": "mintAmount", + "name": "amountIn", "type": "uint256" - } - ], - "name": "mint", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountOutMin", "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "minter", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "mintAmount", + "name": "deadline", "type": "uint256" } ], - "name": "mintBehalf", + "name": "swapExactTokensForTokensAtSupportingFee", "outputs": [ { "internalType": "uint256", - "name": "", + "name": "swapAmount", "type": "uint256" } ], @@ -42063,472 +42119,4049 @@ "type": "function" }, { - "inputs": [], - "name": "name", - "outputs": [ + "inputs": [ { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "", + "name": "to", "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "protocolSeizeShareMantissa", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "protocolShareReserve", + "name": "swapTokensForExactBNB", "outputs": [ { - "internalType": "address payable", - "name": "", - "type": "address" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "uint256", - "name": "redeemTokens", + "name": "amountOut", "type": "uint256" - } - ], - "name": "redeem", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountInMax", "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { "inputs": [ { "internalType": "uint256", - "name": "redeemAmount", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "name": "redeemUnderlying", + "name": "swapTokensForExactBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokens", "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, { "internalType": "uint256", - "name": "", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], + "name": "swapTokensForExactTokensAndRepay", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, { "internalType": "uint256", - "name": "reduceAmount", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "name": "reduceReserves", + "name": "swapTokensForExactTokensAndSupply", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "renounceOwnership", + "inputs": [ + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullBNBDebtAndRepay", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, { "internalType": "uint256", - "name": "repayAmount", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "name": "repayBorrow", - "outputs": [ + "name": "swapTokensForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, { "internalType": "uint256", - "name": "", + "name": "sweepAmount", "type": "uint256" } ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNBAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VTokenBeacon": { + "address": "0x2b8A1C539ABaC89CbF7E2Bc6987A0A38A5e660D4", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "implementation", + "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": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], "stateMutability": "nonpayable", "type": "function" + } + ] + }, + "VTokenImpl": { + "address": "0x1Db646E1Ab05571AF99e47e8F909801e5C99d37B", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "actualAddAmount", + "type": "uint256" + } + ], + "name": "AddReservesFactorFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowCashNotAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "ForceLiquidateBorrowUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "HealBorrowUnauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "LiquidateAccrueCollateralInterestFailed", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsUintMax", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsZero", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCollateralFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateSeizeLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "MintFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "ProtocolSeizeShareTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemTransferOutNotPossible", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashNotAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashValidation", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RepayBorrowFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetInterestRateModelFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorBoundsCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "TransferNotAllowed", + "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": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" + } + ], + "name": "BadDebtIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" + } + ], + "name": "BadDebtRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "HealBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" + } + ], + "name": "Mint", + "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": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldProtocolSeizeShareMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa", + "type": "uint256" + } + ], + "name": "NewProtocolSeizeShare", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldShortfall", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newShortfall", + "type": "address" + } + ], + "name": "NewShortfallContract", + "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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ProtocolSeize", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "SpreadReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "NO_ERROR", + "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": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "addReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "badDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "recoveredAmount_", + "type": "uint256" + } + ], + "name": "badDebtRecovered", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "bool", + "name": "skipLiquidityCheck", + "type": "bool" + } + ], + "name": "forceLiquidateBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vTokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "healBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "shortfall", + "type": "address" + }, + { + "internalType": "address payable", + "name": "protocolShareReserve", + "type": "address" + } + ], + "internalType": "struct VTokenInterface.RiskManagementInit", + "name": "riskManagement", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "protocolSeizeShareMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "reduceReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "setInterestRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa_", + "type": "uint256" + } + ], + "name": "setProtocolSeizeShare", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "protocolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "setReserveFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "shortfall_", + "type": "address" + } + ], + "name": "setShortfallContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "VToken_vALPACA_DeFi": { + "address": "0x02c5Fb0F26761093D297165e902e96D08576D344", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vANKR_DeFi": { + "address": "0x19CE11C8817a1828D1d357DFBF62dCf5b0B2A362", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vBNBx_LiquidStakedBNB": { + "address": "0x5E21bF67a6af41c74C1773E4b473ca5ce8fd3791", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vBSW_DeFi": { + "address": "0x8f657dFD3a1354DEB4545765fE6840cc54AFd379", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vBTT_Tron": { + "address": "0x49c26e12959345472E2Fd95E5f79F8381058d3Ee", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vFLOKI_GameFi": { + "address": "0xc353B7a1E13dDba393B5E120D4169Da7185aA2cb", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vHAY_Stablecoins": { + "address": "0xCa2D81AA7C09A1a025De797600A7081146dceEd9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vNFT_Tron": { + "address": "0x85baA9CD6186B416Ef92c0587Cd9E9Be3BCe2a4D", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vPLANET_DeFi": { + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vRACA_GameFi": { + "address": "0xE5FE5527A5b76C75eedE77FdFA6B80D52444A465", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vSnBNB_LiquidStakedBNB": { + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vTRX_Tron": { + "address": "0x836beb2cB723C498136e1119248436A645845F4E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDD_DeFi": { + "address": "0xA615467caE6B9E0bb98BC04B4411d9296fd1dFa0", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDD_GameFi": { + "address": "0x9f2FD23bd0A5E08C5f2b9DD6CF9C96Bfb5fA515C", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDD_LiquidStakedBNB": { + "address": "0x3ee4be3425e5CC72445cd4C5325A6B5A15507670", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDD_Stablecoins": { + "address": "0xc3a45ad8812189cAb659aD99E64B1376f6aCD035", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDD_Tron": { + "address": "0xf1da185CCe5BeD1BeBbb3007Ef738Ea4224025F7", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_DeFi": { + "address": "0x1D8bBDE12B6b34140604E18e9f9c6e14deC16854", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_GameFi": { + "address": "0x4978591f17670A846137d9d613e333C38dc68A37", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_LiquidStakedBNB": { + "address": "0xB3CD745D46A7551C7DF21e0DEfEB710f546bca62", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "borrower", + "name": "beacon", "type": "address" }, { - "internalType": "uint256", - "name": "repayAmount", - "type": "uint256" - } - ], - "name": "repayBorrowBehalf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reserveFactorMantissa", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "liquidator", + "name": "previousAdmin", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "borrower", + "name": "newAdmin", "type": "address" - }, - { - "internalType": "uint256", - "name": "seizeTokens", - "type": "uint256" } ], - "name": "seize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "accessControlManager_", + "name": "beacon", "type": "address" } ], - "name": "setAccessControlManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "contract InterestRateModel", - "name": "newInterestRateModel", + "indexed": true, + "internalType": "address", + "name": "implementation", "type": "address" } ], - "name": "setInterestRateModel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "newProtocolSeizeShareMantissa_", - "type": "uint256" - } - ], - "name": "setProtocolSeizeShare", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_Stablecoins": { + "address": "0x5e3072305F9caE1c7A82F6Fe9E38811c74922c3B", + "abi": [ { "inputs": [ { - "internalType": "address payable", - "name": "protocolShareReserve_", + "internalType": "address", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "setProtocolShareReserve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "newReserveFactorMantissa", - "type": "uint256" + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "name": "setReserveFactor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "shortfall_", + "name": "beacon", "type": "address" } ], - "name": "setShortfallContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "inputs": [], - "name": "shortfall", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "inputs": [], - "name": "supplyRatePerBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_Tron": { + "address": "0x281E5378f99A4bc55b295ABc0A3E7eD32Deba059", + "abi": [ { "inputs": [ { - "internalType": "contract IERC20Upgradeable", - "name": "token", + "internalType": "address", + "name": "beacon", "type": "address" - } - ], - "name": "sweepToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ + }, { - "internalType": "string", - "name": "", - "type": "string" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { - "inputs": [], - "name": "totalBorrows", - "outputs": [ + "anonymous": false, + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { - "inputs": [], - "name": "totalBorrowsCurrent", - "outputs": [ + "anonymous": false, + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "inputs": [], - "name": "totalReserves", - "outputs": [ + "anonymous": false, + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vWBNB_LiquidStakedBNB": { + "address": "0xe10E80B7FD3a29fE46E16C30CC8F4dd938B742e2", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "dst", + "name": "beacon", "type": "address" }, { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "src", + "name": "previousAdmin", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "dst", + "name": "newAdmin", "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "beacon", "type": "address" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "inputs": [], - "name": "underlying", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" } ] }, - "VToken_vALPACA_DeFi": { - "address": "0x02c5Fb0F26761093D297165e902e96D08576D344", + "VToken_vWIN_Tron": { + "address": "0xb114cfA615c828D88021a41bFc524B800E64a9D5", "abi": [ { "inputs": [ @@ -42601,8 +46234,8 @@ } ] }, - "VToken_vANKR_DeFi": { - "address": "0x19CE11C8817a1828D1d357DFBF62dCf5b0B2A362", + "VToken_vagEUR_Stablecoins": { + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "abi": [ { "inputs": [ @@ -42675,8 +46308,8 @@ } ] }, - "VToken_vBNBx_LiquidStakedBNB": { - "address": "0x5E21bF67a6af41c74C1773E4b473ca5ce8fd3791", + "VToken_vankrBNB_DeFi": { + "address": "0x53728FD51060a85ac41974C6C3Eb1DaE42776723", "abi": [ { "inputs": [ @@ -42749,8 +46382,8 @@ } ] }, - "VToken_vBSW_DeFi": { - "address": "0x8f657dFD3a1354DEB4545765fE6840cc54AFd379", + "VToken_vankrBNB_LiquidStakedBNB": { + "address": "0xBfe25459BA784e70E2D7a718Be99a1f3521cA17f", "abi": [ { "inputs": [ @@ -42823,8 +46456,8 @@ } ] }, - "VToken_vBTT_Tron": { - "address": "0x49c26e12959345472E2Fd95E5f79F8381058d3Ee", + "VToken_vstkBNB_LiquidStakedBNB": { + "address": "0xcc5D9e502574cda17215E70bC0B4546663785227", "abi": [ { "inputs": [ @@ -42897,15 +46530,116 @@ } ] }, - "VToken_vFLOKI_GameFi": { - "address": "0xc353B7a1E13dDba393B5E120D4169Da7185aA2cb", + "ProtocolShareReserve": { + "address": "0xCa01D5A9A248a830E9D93231e791B1afFed7c446", "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", @@ -42913,27 +46647,61 @@ "type": "bytes" } ], + "name": "upgradeToAndCall", + "outputs": [], "stateMutability": "payable", - "type": "constructor" + "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" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "sender", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "calledContract", "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "name": "AdminChanged", - "type": "event" + "name": "Unauthorized", + "type": "error" }, { "anonymous": false, @@ -42941,11 +46709,35 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "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": "BeaconUpgraded", + "name": "AssetReleased", "type": "event" }, { @@ -42954,59 +46746,85 @@ { "indexed": true, "internalType": "address", - "name": "implementation", + "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": "Upgraded", + "name": "AssetsReservesUpdated", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vHAY_Stablecoins": { - "address": "0xCa2D81AA7C09A1a025De797600A7081146dceEd9", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "beacon", + "name": "destination", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "DistributionConfigAdded", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "previousAdmin", + "name": "destination", "type": "address" }, { "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" } ], - "name": "AdminChanged", + "name": "DistributionConfigRemoved", "type": "event" }, { @@ -43015,54 +46833,62 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "destination", "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "oldPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "newPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" } ], - "name": "BeaconUpgraded", + "name": "DistributionConfigUpdated", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "Upgraded", + "name": "Initialized", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vNFT_Tron": { - "address": "0x85baA9CD6186B416Ef92c0587Cd9E9Be3BCe2a4D", - "abi": [ - { + "anonymous": false, "inputs": [ { - "internalType": "address", - "name": "beacon", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "MaxLoopsLimitUpdated", + "type": "event" }, { "anonymous": false, @@ -43070,17 +46896,17 @@ { "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "oldAccessControlManager", "type": "address" }, { "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "newAccessControlManager", "type": "address" } ], - "name": "AdminChanged", + "name": "NewAccessControlManager", "type": "event" }, { @@ -43089,11 +46915,17 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", "type": "address" } ], - "name": "BeaconUpgraded", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -43102,504 +46934,593 @@ { "indexed": true, "internalType": "address", - "name": "implementation", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", "type": "address" } ], - "name": "Upgraded", + "name": "OwnershipTransferred", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vRACA_GameFi": { - "address": "0xE5FE5527A5b76C75eedE77FdFA6B80D52444A465", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "beacon", + "name": "oldPoolRegistry", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "PoolRegistryUpdated", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "previousAdmin", + "name": "comptroller", "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "newAdmin", + "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": "AdminChanged", + "name": "ReservesUpdated", "type": "event" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "", "type": "address" } ], - "name": "Upgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vTRX_Tron": { - "address": "0x836beb2cB723C498136e1119248436A645845F4E", - "abi": [ - { - "inputs": [ + "inputs": [], + "name": "accessControlManager", + "outputs": [ { - "internalType": "address", - "name": "beacon", + "internalType": "contract IAccessControlManagerV8", + "name": "", "type": "address" - }, + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "", "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" } ], - "name": "AdminChanged", - "type": "event" + "name": "assetsReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "percentage", + "type": "uint8" + }, + { "internalType": "address", - "name": "beacon", + "name": "destination", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "destination", "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_DeFi": { - "address": "0xA615467caE6B9E0bb98BC04B4411d9296fd1dFa0", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "comptroller", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "getUnreleasedFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "_accessControlManager", "type": "address" }, { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "pendingOwner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "", "type": "address" } ], - "name": "Upgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [], + "name": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_GameFi": { - "address": "0x9f2FD23bd0A5E08C5f2b9DD6CF9C96Bfb5fA515C", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "comptroller", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "address[]", + "name": "assets", + "type": "address[]" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "destination", "type": "address" } ], - "name": "AdminChanged", - "type": "event" + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "accessControlManager_", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "_poolRegistry", "type": "address" } ], - "name": "Upgraded", - "type": "event" + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAssetReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_LiquidStakedBNB": { - "address": "0x3ee4be3425e5CC72445cd4C5325A6B5A15507670", - "abi": [ + "inputs": [], + "name": "totalDistributions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "newOwner", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "comptroller", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "asset", "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" } ], - "name": "AdminChanged", - "type": "event" + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "vBNB", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "_logic", "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_Stablecoins": { - "address": "0xc3a45ad8812189cAb659aD99E64B1376f6aCD035", - "abi": [ - { - "inputs": [ + }, { "internalType": "address", - "name": "beacon", + "name": "admin_", "type": "address" }, { "internalType": "bytes", - "name": "data", + "name": "_data", "type": "bytes" } ], "stateMutability": "payable", "type": "constructor" - }, + } + ] + }, + "ProtocolShareReserve_Implementation": { + "address": "0x5108E5F903Ecc5e3a2dA20171527aCe96CB3c7f8", + "abi": [ { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "_corePoolComptroller", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "_wbnb", "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "_vbnb", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "nonpayable", + "type": "constructor" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" + "inputs": [], + "name": "InvalidAddress", + "type": "error" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [], + "name": "InvalidTotalPercentage", + "type": "error" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_Tron": { - "address": "0xf1da185CCe5BeD1BeBbb3007Ef738Ea4224025F7", - "abi": [ { "inputs": [ { - "internalType": "address", - "name": "beacon", - "type": "address" + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "MaxLoopsLimitExceeded", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "sender", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "calledContract", "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "name": "AdminChanged", - "type": "event" + "name": "Unauthorized", + "type": "error" }, { "anonymous": false, @@ -43607,11 +47528,35 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "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": "BeaconUpgraded", + "name": "AssetReleased", "type": "event" }, { @@ -43620,59 +47565,85 @@ { "indexed": true, "internalType": "address", - "name": "implementation", + "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": "Upgraded", + "name": "AssetsReservesUpdated", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_DeFi": { - "address": "0x1D8bBDE12B6b34140604E18e9f9c6e14deC16854", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "beacon", + "name": "destination", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "DistributionConfigAdded", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "previousAdmin", + "name": "destination", "type": "address" }, { "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" } ], - "name": "AdminChanged", + "name": "DistributionConfigRemoved", "type": "event" }, { @@ -43681,54 +47652,62 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "destination", "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "oldPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "newPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" } ], - "name": "BeaconUpgraded", + "name": "DistributionConfigUpdated", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "Upgraded", + "name": "Initialized", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_GameFi": { - "address": "0x4978591f17670A846137d9d613e333C38dc68A37", - "abi": [ - { + "anonymous": false, "inputs": [ { - "internalType": "address", - "name": "beacon", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "MaxLoopsLimitUpdated", + "type": "event" }, { "anonymous": false, @@ -43736,17 +47715,17 @@ { "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "oldAccessControlManager", "type": "address" }, { "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "newAccessControlManager", "type": "address" } ], - "name": "AdminChanged", + "name": "NewAccessControlManager", "type": "event" }, { @@ -43755,72 +47734,55 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "previousOwner", "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { "indexed": true, "internalType": "address", - "name": "implementation", + "name": "newOwner", "type": "address" } ], - "name": "Upgraded", + "name": "OwnershipTransferStarted", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_LiquidStakedBNB": { - "address": "0xB3CD745D46A7551C7DF21e0DEfEB710f546bca62", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "beacon", + "name": "previousOwner", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "OwnershipTransferred", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "previousAdmin", + "name": "oldPoolRegistry", "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "newAdmin", + "name": "newPoolRegistry", "type": "address" } ], - "name": "AdminChanged", + "name": "PoolRegistryUpdated", "type": "event" }, { @@ -43829,493 +47791,482 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "comptroller", "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { "indexed": true, "internalType": "address", - "name": "implementation", + "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": "Upgraded", + "name": "ReservesUpdated", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_Stablecoins": { - "address": "0x5e3072305F9caE1c7A82F6Fe9E38811c74922c3B", - "abi": [ - { - "inputs": [ + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ { "internalType": "address", - "name": "beacon", + "name": "", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [ { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint8", + "name": "", + "type": "uint8" } ], - "name": "AdminChanged", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "WBNB", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", + "internalType": "contract IAccessControlManagerV8", + "name": "", "type": "address" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "stateMutability": "view", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_Tron": { - "address": "0x281E5378f99A4bc55b295ABc0A3E7eD32Deba059", - "abi": [ { "inputs": [ { - "internalType": "address", - "name": "beacon", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "components": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "", "type": "address" + }, + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "", + "type": "uint8" } ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "assetsReserves", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "distributionTargets", + "outputs": [ + { + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "percentage", + "type": "uint8" + }, + { "internalType": "address", - "name": "implementation", + "name": "destination", "type": "address" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "stateMutability": "view", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vWBNB_LiquidStakedBNB": { - "address": "0xe10E80B7FD3a29fE46E16C30CC8F4dd938B742e2", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "destination", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "getPercentageDistribution", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "comptroller", "type": "address" }, { - "indexed": false, + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" + }, + { "internalType": "address", - "name": "newAdmin", + "name": "destination", "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "asset", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "getUnreleasedFunds", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "stateMutability": "view", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vWIN_Tron": { - "address": "0xb114cfA615c828D88021a41bFc524B800E64a9D5", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "_accessControlManager", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "_loopsLimit", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "", "type": "address" } ], - "name": "AdminChanged", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "pendingOwner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "poolRegistry", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "", "type": "address" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "stateMutability": "view", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vagEUR_Stablecoins": { - "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "comptroller", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "address[]", + "name": "assets", + "type": "address[]" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" + "internalType": "enum ProtocolShareReserve.Schema", + "name": "schema", + "type": "uint8" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "destination", "type": "address" } ], - "name": "AdminChanged", - "type": "event" + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "accessControlManager_", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "_poolRegistry", "type": "address" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vankrBNB_DeFi": { - "address": "0x53728FD51060a85ac41974C6C3Eb1DaE42776723", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "", "type": "address" - }, + } + ], + "name": "totalAssetReserve", + "outputs": [ { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, + "inputs": [], + "name": "totalDistributions", + "outputs": [ { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "newOwner", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "stateMutability": "payable", - "type": "receive" + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" } ] }, - "VToken_vankrBNB_LiquidStakedBNB": { - "address": "0xBfe25459BA784e70E2D7a718Be99a1f3521cA17f", + "ProtocolShareReserve_Proxy": { + "address": "0xCa01D5A9A248a830E9D93231e791B1afFed7c446", "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", "type": "address" }, { "internalType": "bytes", - "name": "data", + "name": "_data", "type": "bytes" } ], @@ -44372,78 +48323,74 @@ "type": "fallback" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vstkBNB_LiquidStakedBNB": { - "address": "0xcc5D9e502574cda17215E70bC0B4546663785227", - "abi": [ - { - "inputs": [ + "inputs": [], + "name": "admin", + "outputs": [ { "internalType": "address", - "name": "beacon", + "name": "admin_", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "newAdmin", "type": "address" - }, + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "implementation_", "type": "address" } ], - "name": "AdminChanged", - "type": "event" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "newImplementation", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "newImplementation", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "Upgraded", - "type": "event" - }, - { + "name": "upgradeToAndCall", + "outputs": [], "stateMutability": "payable", - "type": "fallback" + "type": "function" }, { "stateMutability": "payable", diff --git a/deployments/bscmainnet/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json b/deployments/bscmainnet/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json new file mode 100644 index 000000000..3d6dc8c9d --- /dev/null +++ b/deployments/bscmainnet/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json @@ -0,0 +1,497 @@ +{ + "address": "0x53DbE3c0d1Bd439E4F600ad36791C41d02906E6b", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0x17d9a628e4f202f780c1a521a0cd36f1c26faab79b5ad75ec83e72f89a059e3e", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0x53DbE3c0d1Bd439E4F600ad36791C41d02906E6b", + "transactionIndex": 105, + "gasUsed": "554524", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000", + "blockHash": "0x02017b0b4832841b0c8f914a2c7663698aa7ad2314bd85298126589b103a2d44", + "transactionHash": "0x17d9a628e4f202f780c1a521a0cd36f1c26faab79b5ad75ec83e72f89a059e3e", + "logs": [ + { + "transactionIndex": 105, + "blockNumber": 33136370, + "transactionHash": "0x17d9a628e4f202f780c1a521a0cd36f1c26faab79b5ad75ec83e72f89a059e3e", + "address": "0x53DbE3c0d1Bd439E4F600ad36791C41d02906E6b", + "topics": ["0x6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d"], + "data": "0x0000000000000000000000000000000000000000000000000000000071672e7f000000000000000000000000000000000000000000000000000000046e07d0f60000000000000000000000000000000000000000000000000000004272753e6d000000000000000000000000000000000000000000000000063eb89da4ed0000", + "logIndex": 325, + "blockHash": "0x02017b0b4832841b0c8f914a2c7663698aa7ad2314bd85298126589b103a2d44" + } + ], + "blockNumber": 33136370, + "cumulativeGasUsed": "16056329", + "status": 1, + "byzantium": true + }, + "args": [ + "20000000000000000", + "200000000000000000", + "3000000000000000000", + "450000000000000000", + "0x4788629ABc6cFCA10F9f969efdEAa1cF70c23555" + ], + "numDeployments": 1, + "solcInputHash": "82cd33260a9b17bbce6d70381b9dc2d8", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"},{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":false,\"internalType\":\"uint256\",\"name\":\"baseRatePerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"kink\",\"type\":\"uint256\"}],\"name\":\"NewInterestParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"jumpMultiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"kink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"multiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"}],\"name\":\"updateJumpRateModel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"utilizationRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Arr00\",\"kind\":\"dev\",\"methods\":{\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The borrow rate percentage per block as a mantissa (scaled by 1e18)\"}},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserveFactorMantissa\":\"The current reserve factor for the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\"}},\"isInterestRateModel()\":{\"returns\":{\"_0\":\"Always true\"}},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized if the sender is not allowed to call this function\",\"params\":{\"baseRatePerYear\":\"The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\",\"jumpMultiplierPerYear\":\"The multiplierPerBlock after hitting a specified utilization point\",\"kink_\":\"The utilization point at which the jump multiplier is applied\",\"multiplierPerYear\":\"The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\"}},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market (currently unused)\"},\"returns\":{\"_0\":\"The utilization rate as a mantissa between [0, MANTISSA_ONE]\"}}},\"title\":\"Compound's JumpRateModel Contract V2 for V2 vTokens\",\"version\":1},\"userdoc\":{\"errors\":{\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}]},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"The address of the AccessControlManager contract\"},\"baseRatePerBlock()\":{\"notice\":\"The base interest rate which is the y-intercept when utilization rate is 0\"},\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current borrow rate per block\"},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current supply rate per block\"},\"isInterestRateModel()\":{\"notice\":\"Indicator that this is an InterestRateModel contract (for inspection)\"},\"jumpMultiplierPerBlock()\":{\"notice\":\"The multiplier per block after hitting a specified utilization point\"},\"kink()\":{\"notice\":\"The utilization point at which the jump multiplier is applied\"},\"multiplierPerBlock()\":{\"notice\":\"The multiplier of utilization rate that gives the slope of the interest rate\"},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"notice\":\"Update the parameters of the interest rate model\"},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\"}},\"notice\":\"Supports only for V2 vTokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JumpRateModelV2.sol\":\"JumpRateModelV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\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\":\"0x41deef84d1839590b243b66506691fde2fb938da01eabde53e82d3b8316fdaf9\",\"license\":\"BSD-3-Clause\"},\"contracts/BaseJumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { BLOCKS_PER_YEAR, EXP_SCALE, MANTISSA_ONE } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Logic for Compound's JumpRateModel Contract V2.\\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\\n */\\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\\n /**\\n * @notice The address of the AccessControlManager contract\\n */\\n IAccessControlManagerV8 public accessControlManager;\\n\\n /**\\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\\n */\\n uint256 public multiplierPerBlock;\\n\\n /**\\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\\n */\\n uint256 public baseRatePerBlock;\\n\\n /**\\n * @notice The multiplier per block after hitting a specified utilization point\\n */\\n uint256 public jumpMultiplierPerBlock;\\n\\n /**\\n * @notice The utilization point at which the jump multiplier is applied\\n */\\n uint256 public kink;\\n\\n event NewInterestParams(\\n uint256 baseRatePerBlock,\\n uint256 multiplierPerBlock,\\n uint256 jumpMultiplierPerBlock,\\n uint256 kink\\n );\\n\\n /**\\n * @notice Thrown when the action is prohibited by AccessControlManager\\n */\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Construct an interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @param accessControlManager_ The address of the AccessControlManager contract\\n */\\n constructor(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n ) {\\n require(address(accessControlManager_) != address(0), \\\"invalid ACM address\\\");\\n\\n accessControlManager = accessControlManager_;\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @custom:error Unauthorized if the sender is not allowed to call this function\\n * @custom:access Controlled by AccessControlManager\\n */\\n function updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) external virtual {\\n string memory signature = \\\"updateJumpRateModel(uint256,uint256,uint256,uint256)\\\";\\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Calculates the current supply rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param reserveFactorMantissa The current reserve factor for the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) public view virtual override returns (uint256) {\\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\\n uint256 incomeToDistribute = borrows * rateToPool;\\n uint256 supply = cash + borrows + badDebt - reserves;\\n return incomeToDistribute / supply;\\n }\\n\\n /**\\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market (currently unused)\\n * @param badDebt The amount of badDebt in the market\\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\\n */\\n function utilizationRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) public pure returns (uint256) {\\n // Utilization rate is 0 when there are no borrows and badDebt\\n if ((borrows + badDebt) == 0) {\\n return 0;\\n }\\n\\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\\n\\n if (rate > EXP_SCALE) {\\n rate = EXP_SCALE;\\n }\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Internal function to update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n */\\n function _updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) internal {\\n baseRatePerBlock = baseRatePerYear / BLOCKS_PER_YEAR;\\n multiplierPerBlock = multiplierPerYear / BLOCKS_PER_YEAR;\\n jumpMultiplierPerBlock = jumpMultiplierPerYear / BLOCKS_PER_YEAR;\\n kink = kink_;\\n\\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function _getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) internal view returns (uint256) {\\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\\n uint256 kink_ = kink;\\n\\n if (util <= kink_) {\\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n }\\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n uint256 excessUtil;\\n unchecked {\\n excessUtil = util - kink_;\\n }\\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\\n }\\n}\\n\",\"keccak256\":\"0xaaceeecdb6212410755c76c61024f235f105279cd3b040f4d43578276243754b\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"contracts/JumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { BaseJumpRateModelV2 } from \\\"./BaseJumpRateModelV2.sol\\\";\\n\\n/**\\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\\n * @author Arr00\\n * @notice Supports only for V2 vTokens\\n */\\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\\n constructor(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n )\\n BaseJumpRateModelV2(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_, accessControlManager_)\\n /* solhint-disable-next-line no-empty-blocks */\\n {\\n\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view override returns (uint256) {\\n return _getBorrowRate(cash, borrows, reserves, badDebt);\\n }\\n}\\n\",\"keccak256\":\"0x4ed1afa149d27fbe7ac0f6099c90be41304aff5e45c81b390c357eb5391699c5\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev The approximate number of blocks per year that is assumed by the interest rate model\\nuint256 constant BLOCKS_PER_YEAR = 10_512_000;\\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\",\"keccak256\":\"0x04cd899695ea593a2529cb6a1a04c2a34bff0c1516bd70a5f638ae7a850cad8b\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506040516108be3803806108be83398101604081905261002f91610150565b84848484846001600160a01b03811661008e5760405162461bcd60e51b815260206004820152601360248201527f696e76616c69642041434d206164647265737300000000000000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b0383161790556100b5858585856100c4565b505050505050505050506101cd565b6100d162a06680856101ab565b6002556100e162a06680846101ab565b6001556100f162a06680836101ab565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b600080600080600060a0868803121561016857600080fd5b855160208701516040880151606089015160808a0151939850919650945092506001600160a01b038116811461019d57600080fd5b809150509295509295909350565b6000826101c857634e487b7160e01b600052601260045260246000fd5b500490565b6106e2806101dc6000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c80638726bb89116100665780638726bb8914610113578063b4a0bdf31461011c578063b9f9850a14610147578063f14039de14610150578063fd2da3391461015957600080fd5b8063073b8a74146100a35780630cde8d1c146100c95780632037f3e7146100dc5780632191f92a146100f157806370d3c43f14610100575b600080fd5b6100b66100b13660046104bf565b610162565b6040519081526020015b60405180910390f35b6100b66100d73660046104f1565b61017b565b6100ef6100ea3660046104bf565b61020e565b005b604051600181526020016100c0565b6100b661010e3660046104bf565b6102e5565b6100b660015481565b60005461012f906001600160a01b031681565b6040516001600160a01b0390911681526020016100c0565b6100b660035481565b6100b660025481565b6100b660045481565b60006101708585858561036e565b90505b949350505050565b60008061019084670de0b6b3a7640000610542565b905060006101a08888888761036e565b90506000670de0b6b3a76400006101b78484610559565b6101c19190610578565b905060006101cf828a610559565b9050600088876101df8c8e61059a565b6101e9919061059a565b6101f39190610542565b90506101ff8183610578565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161067960349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab9061026190339086906004016105ff565b602060405180830381865afa15801561027e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a29190610623565b9050806102d157333083604051634a3fa29360e01b81526004016102c89392919061064c565b60405180910390fd5b6102dd86868686610433565b505050505050565b60006102f1828561059a565b60000361030057506000610173565b6000838361030e878961059a565b610318919061059a565b6103229190610542565b670de0b6b3a7640000610335858861059a565b61033f9190610559565b6103499190610578565b9050670de0b6b3a76400008111156101705750670de0b6b3a764000095945050505050565b60008061037d868686866102e5565b6004549091508082116103c157600254670de0b6b3a7640000600154846103a49190610559565b6103ae9190610578565b6103b8919061059a565b92505050610173565b6000600254670de0b6b3a7640000600154846103dd9190610559565b6103e79190610578565b6103f1919061059a565b90506000828403905081670de0b6b3a7640000600354836104129190610559565b61041c9190610578565b610426919061059a565b9998505050505050505050565b61044062a0668085610578565b60025561045062a0668084610578565b60015561046062a0668083610578565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b600080600080608085870312156104d557600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561050957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105545761055461052c565b500390565b60008160001904831182151516156105735761057361052c565b500290565b60008261059557634e487b7160e01b600052601260045260246000fd5b500490565b600082198211156105ad576105ad61052c565b500190565b6000815180845260005b818110156105d8576020818501810151868301820152016105bc565b818111156105ea576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090610173908301846105b2565b60006020828403121561063557600080fd5b8151801515811461064557600080fd5b9392505050565b6001600160a01b03848116825283166020820152606060408201819052600090610170908301846105b256fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a26469706673582212206a37cebdb4b862acc229f004fa6e49bdd6e972410e73f5a533c3930dca0b66a464736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061009e5760003560e01c80638726bb89116100665780638726bb8914610113578063b4a0bdf31461011c578063b9f9850a14610147578063f14039de14610150578063fd2da3391461015957600080fd5b8063073b8a74146100a35780630cde8d1c146100c95780632037f3e7146100dc5780632191f92a146100f157806370d3c43f14610100575b600080fd5b6100b66100b13660046104bf565b610162565b6040519081526020015b60405180910390f35b6100b66100d73660046104f1565b61017b565b6100ef6100ea3660046104bf565b61020e565b005b604051600181526020016100c0565b6100b661010e3660046104bf565b6102e5565b6100b660015481565b60005461012f906001600160a01b031681565b6040516001600160a01b0390911681526020016100c0565b6100b660035481565b6100b660025481565b6100b660045481565b60006101708585858561036e565b90505b949350505050565b60008061019084670de0b6b3a7640000610542565b905060006101a08888888761036e565b90506000670de0b6b3a76400006101b78484610559565b6101c19190610578565b905060006101cf828a610559565b9050600088876101df8c8e61059a565b6101e9919061059a565b6101f39190610542565b90506101ff8183610578565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161067960349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab9061026190339086906004016105ff565b602060405180830381865afa15801561027e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a29190610623565b9050806102d157333083604051634a3fa29360e01b81526004016102c89392919061064c565b60405180910390fd5b6102dd86868686610433565b505050505050565b60006102f1828561059a565b60000361030057506000610173565b6000838361030e878961059a565b610318919061059a565b6103229190610542565b670de0b6b3a7640000610335858861059a565b61033f9190610559565b6103499190610578565b9050670de0b6b3a76400008111156101705750670de0b6b3a764000095945050505050565b60008061037d868686866102e5565b6004549091508082116103c157600254670de0b6b3a7640000600154846103a49190610559565b6103ae9190610578565b6103b8919061059a565b92505050610173565b6000600254670de0b6b3a7640000600154846103dd9190610559565b6103e79190610578565b6103f1919061059a565b90506000828403905081670de0b6b3a7640000600354836104129190610559565b61041c9190610578565b610426919061059a565b9998505050505050505050565b61044062a0668085610578565b60025561045062a0668084610578565b60015561046062a0668083610578565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b600080600080608085870312156104d557600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561050957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105545761055461052c565b500390565b60008160001904831182151516156105735761057361052c565b500290565b60008261059557634e487b7160e01b600052601260045260246000fd5b500490565b600082198211156105ad576105ad61052c565b500190565b6000815180845260005b818110156105d8576020818501810151868301820152016105bc565b818111156105ea576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090610173908301846105b2565b60006020828403121561063557600080fd5b8151801515811461064557600080fd5b9392505050565b6001600160a01b03848116825283166020820152606060408201819052600090610170908301846105b256fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a26469706673582212206a37cebdb4b862acc229f004fa6e49bdd6e972410e73f5a533c3930dca0b66a464736f6c634300080d0033", + "devdoc": { + "author": "Arr00", + "kind": "dev", + "methods": { + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The borrow rate percentage per block as a mantissa (scaled by 1e18)" + } + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserveFactorMantissa": "The current reserve factor for the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)" + } + }, + "isInterestRateModel()": { + "returns": { + "_0": "Always true" + } + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized if the sender is not allowed to call this function", + "params": { + "baseRatePerYear": "The approximate target base APR, as a mantissa (scaled by EXP_SCALE)", + "jumpMultiplierPerYear": "The multiplierPerBlock after hitting a specified utilization point", + "kink_": "The utilization point at which the jump multiplier is applied", + "multiplierPerYear": "The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)" + } + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market (currently unused)" + }, + "returns": { + "_0": "The utilization rate as a mantissa between [0, MANTISSA_ONE]" + } + } + }, + "title": "Compound's JumpRateModel Contract V2 for V2 vTokens", + "version": 1 + }, + "userdoc": { + "errors": { + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ] + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "The address of the AccessControlManager contract" + }, + "baseRatePerBlock()": { + "notice": "The base interest rate which is the y-intercept when utilization rate is 0" + }, + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current borrow rate per block" + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current supply rate per block" + }, + "isInterestRateModel()": { + "notice": "Indicator that this is an InterestRateModel contract (for inspection)" + }, + "jumpMultiplierPerBlock()": { + "notice": "The multiplier per block after hitting a specified utilization point" + }, + "kink()": { + "notice": "The utilization point at which the jump multiplier is applied" + }, + "multiplierPerBlock()": { + "notice": "The multiplier of utilization rate that gives the slope of the interest rate" + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "notice": "Update the parameters of the interest rate model" + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`" + } + }, + "notice": "Supports only for V2 vTokens", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7416, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "accessControlManager", + "offset": 0, + "slot": "0", + "type": "t_contract(IAccessControlManagerV8)5203" + }, + { + "astId": 7419, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "multiplierPerBlock", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 7422, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "baseRatePerBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 7425, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "jumpMultiplierPerBlock", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 7428, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "kink", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_contract(IAccessControlManagerV8)5203": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/bscmainnet/ProtocolShareReserve_Implementation.json b/deployments/bscmainnet/ProtocolShareReserve_Implementation.json deleted file mode 100644 index b8203fb11..000000000 --- a/deployments/bscmainnet/ProtocolShareReserve_Implementation.json +++ /dev/null @@ -1,711 +0,0 @@ -{ - "address": "0xc1c56732FcaFca0F66D59745Ec69DC642EC20ab8", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "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": "comptroller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsReleased", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "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": "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": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "assetsReserves", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "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": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "protocolIncome_", - "type": "address" - }, - { - "internalType": "address", - "name": "riskFund_", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "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": [], - "name": "protocolIncome", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "releaseFunds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "riskFund", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "poolRegistry_", - "type": "address" - } - ], - "name": "setPoolRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "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" - } - ], - "transactionHash": "0xcae7176a7194c5a1374753b1283f725e3eaa770ce3967fb2fbc18d45c80b917d", - "receipt": { - "to": null, - "from": "0x55A9f5374Af30E3045FB491f1da3C2E8a74d168D", - "contractAddress": "0xc1c56732FcaFca0F66D59745Ec69DC642EC20ab8", - "transactionIndex": 74, - "gasUsed": "1213372", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000001000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000", - "blockHash": "0x38e50f3359ec0526f0a64abf1c0c3c793433e1a8c333a9f94d4fbb200bb394cd", - "transactionHash": "0xcae7176a7194c5a1374753b1283f725e3eaa770ce3967fb2fbc18d45c80b917d", - "logs": [ - { - "transactionIndex": 74, - "blockNumber": 31670920, - "transactionHash": "0xcae7176a7194c5a1374753b1283f725e3eaa770ce3967fb2fbc18d45c80b917d", - "address": "0xc1c56732FcaFca0F66D59745Ec69DC642EC20ab8", - "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], - "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 143, - "blockHash": "0x38e50f3359ec0526f0a64abf1c0c3c793433e1a8c333a9f94d4fbb200bb394cd" - } - ], - "blockNumber": 31670920, - "cumulativeGasUsed": "6522203", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "394b060e0e484d4aa39aea929deecf07", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"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\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FundsReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"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\":\"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\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"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\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"protocolIncome_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"riskFund_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":[],\"name\":\"protocolIncome\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"releaseFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"riskFund\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"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\":{\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"getPoolAssetReserve(address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when asset address is zero\",\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Asset's reserve in risk fund.\"}},\"initialize(address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when protocol income address is zeroZeroAddressNotAllowed is thrown when risk fund address is zero\",\"params\":{\"protocolIncome_\":\"The address protocol income will be sent to\",\"riskFund_\":\"Risk fund address\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"releaseFunds(address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when asset address is zero\",\"params\":{\"amount\":\"Amount to release\",\"asset\":\"Asset to be released\",\"comptroller\":\"Pool's Comptroller\"},\"returns\":{\"_0\":\"Number of total released tokens\"}},\"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.\"},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"sweepToken(address,address)\":{\"custom:access\":\"Only Owner\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when asset address is zero\",\"params\":{\"_to\":\"Recipient of the output tokens.\",\"_token\":\"The address of the BEP-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)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool)\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"FundsReleased(address,address,uint256)\":{\"notice\":\"Emitted when funds are released\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"}},\"kind\":\"user\",\"methods\":{\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"initialize(address,address)\":{\"notice\":\"Initializes the deployer to owner.\"},\"releaseFunds(address,address,uint256)\":{\"notice\":\"Release funds\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter.\"},\"sweepToken(address,address)\":{\"notice\":\"A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/ProtocolShareReserve.sol\":\"ProtocolShareReserve\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"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/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.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"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 Venus Access Control Contract.\\n * @dev The AccessControlledV8 contract is a wrapper around the OpenZeppelin AccessControl contract\\n * It provides a standardized way to control access to methods within the Venus Smart Contract Ecosystem.\\n * The contract allows the owner to set an AccessControlManager contract address.\\n * It can restrict method calls based on the sender's role and the method's signature.\\n */\\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\":\"0x618d942756b93e02340a42f3c80aa99fc56be1a96861f5464dc23a76bf30b3a5\",\"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\\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\":\"0x41deef84d1839590b243b66506691fde2fb938da01eabde53e82d3b8316fdaf9\",\"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\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor is changed by admin\\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\n\\n /// @notice Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow.\\n * @param vTokenAddress The address of the asset to be removed\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return NO_ERROR;\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(\\n address vToken,\\n address minter,\\n uint256 mintAmount\\n ) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(\\n address vToken,\\n address borrower,\\n uint256 borrowAmount\\n ) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if the market is deprecated or it is a forced liquidation */\\n if (skipLiquidityCheck || isDeprecated(VToken(vTokenBorrowed))) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external override {\\n _checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = accountAssets[user];\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = accountAssets[borrower];\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n _ensureMaxLoops(numMarkets);\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(\\n VToken[] calldata marketsList,\\n Action[] calldata actionsList,\\n bool paused\\n ) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(address account)\\n external\\n view\\n returns (\\n uint256 error,\\n uint256 liquidity,\\n uint256 shortfall\\n )\\n {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(address account)\\n external\\n view\\n returns (\\n uint256 error,\\n uint256 liquidity,\\n uint256 shortfall\\n )\\n {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall Hypothetical account shortfall below collateral requirements\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n )\\n external\\n view\\n returns (\\n uint256 error,\\n uint256 liquidity,\\n uint256 shortfall\\n )\\n {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Check if a market is marked as listed (active)\\n * @param vToken vToken Address for the market to check\\n * @return listed True if listed otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].isListed;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n VToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the market specified, otherwise false.\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = accountAssets[account];\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\n }\\n\\n /**\\n * @notice Check if a vToken market has been deprecated\\n * @dev All borrows in a deprecated vToken market can be immediately liquidated\\n * @param vToken The market to check if deprecated\\n * @return deprecated True if the given vToken market has been deprecated\\n */\\n function isDeprecated(VToken vToken) public view returns (bool) {\\n return\\n markets[address(vToken)].collateralFactorMantissa == 0 &&\\n actionPaused(address(vToken), Action.BORROW) &&\\n vToken.reserveFactorMantissa() == MANTISSA_ONE;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n }\\n\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionPaused(\\n address market,\\n Action action,\\n bool paused\\n ) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(address account, function(VToken) internal view returns (Exp memory) weight)\\n internal\\n view\\n returns (AccountLiquiditySnapshot memory snapshot)\\n {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = accountAssets[account];\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(VToken vToken, address user)\\n internal\\n view\\n returns (\\n uint256 vTokenBalance,\\n uint256 borrowBalance,\\n uint256 exchangeRateMantissa\\n )\\n {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x73fdb4e4b2a2cfec75b0ef5a19491c4136a7953e1239989fb77ed26c1b7a77ac\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(\\n address vToken,\\n address minter,\\n uint256 mintAmount\\n ) external;\\n\\n function preRedeemHook(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) external;\\n\\n function preBorrowHook(\\n address vToken,\\n address borrower,\\n uint256 borrowAmount\\n ) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function preTransferHook(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x0ac4cc1e962946a665033bc50251c33ce59998e492d9f4a76cf0231bf0b0f545\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // Multiplier representing the most one can borrow against their collateral in this market.\\n // For instance, 0.9 to allow borrowing 90% of collateral value.\\n // Must be between 0 and 1, and stored as a mantissa.\\n uint256 collateralFactorMantissa;\\n // Multiplier representing the collateralization after which the borrow is eligible\\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n // value. Must be between 0 and collateral factor, stored as a mantissa.\\n uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\n enum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n }\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint256 public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n /**\\n * @notice Official mapping of vTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\\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\":\"0x23a035905b74bfbc8840b76690490a67b8861b2025f109fb5ac9fac13be909d3\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x3f8ec4e18bca1fdf8619966f4f6e095e205517a78f8c741b87fe82125754f96f\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(\\n Exp memory a,\\n uint256 scalar,\\n uint256 addend\\n ) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0xc13fcd089aa939e53b9c494c24beed316d572e9d433a44034eefa77915b673ec\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"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\"},\"contracts/Pool/PoolRegistryInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title PoolRegistryInterface\\n * @author Venus\\n * @notice Interface implemented by `PoolRegistry`.\\n */\\ninterface PoolRegistryInterface {\\n /**\\n * @notice Struct for a Venus interest rate pool.\\n */\\n struct VenusPool {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n }\\n\\n /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7e8ccd190ef019a3f8c3fcb67ed3eadd7bed32b263f88566870d138cd95ae312\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each block for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller private comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlock(address[],uint32[],uint32[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumber();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\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 */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumber = getBlockNumber();\\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n function getBlockNumber() public view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumber();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(\\n VToken vToken,\\n uint256 supplySpeed,\\n uint256 borrowSpeed\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplyIndex = supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowIndex = borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\\n blockNumber = supplyState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\\n\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n supplyState.index = safe224(\\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n supplyState.block = blockNumber;\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\\n blockNumber = borrowState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n borrowState.index = safe224(\\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n borrowState.block = blockNumber;\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0x0e5bede4edc4346e689de0adcf98dc9642feb55d44c1916715741c5937a34d52\",\"license\":\"BSD-3-Clause\"},\"contracts/RiskFund/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IProtocolShareReserve\\n * @author Venus\\n * @notice Interface implemented by `ProtocolShareReserve`.\\n */\\ninterface IProtocolShareReserve {\\n function updateAssetsState(address comptroller, address asset) external;\\n}\\n\",\"keccak256\":\"0x45bf43fe09973ebfe0b5d3e81f966d7521b88c118d6ff64c289c500a62a7d564\",\"license\":\"BSD-3-Clause\"},\"contracts/RiskFund/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 swapPoolsAssets(\\n address[] calldata markets,\\n uint256[] calldata amountsOutMin,\\n address[][] calldata paths,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updateAssetsState(address comptroller, address asset) external;\\n\\n function convertibleBaseAsset() external view returns (address);\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xa519791948d96fb81143cdd9db0a2b753a39f1f9ca4e8c68b92997e2095f241a\",\"license\":\"BSD-3-Clause\"},\"contracts/RiskFund/ProtocolShareReserve.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 { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\n\\nimport { IProtocolShareReserve } from \\\"./IProtocolShareReserve.sol\\\";\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { ReserveHelpers } from \\\"./ReserveHelpers.sol\\\";\\nimport { IRiskFund } from \\\"./IRiskFund.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\ncontract ProtocolShareReserve is ExponentialNoError, ReserveHelpers, IProtocolShareReserve {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n address public protocolIncome;\\n address public riskFund;\\n // Percentage of funds not sent to the RiskFund contract when the funds are released, following the project Tokenomics\\n uint256 private constant PROTOCOL_SHARE_PERCENTAGE = 50;\\n uint256 private constant BASE_UNIT = 100;\\n\\n /// @notice Emitted when funds are released\\n event FundsReleased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\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 /**\\n * @notice Initializes the deployer to owner.\\n * @param protocolIncome_ The address protocol income will be sent to\\n * @param riskFund_ Risk fund address\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol income address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when risk fund address is zero\\n */\\n function initialize(address protocolIncome_, address riskFund_) external initializer {\\n ensureNonzeroAddress(protocolIncome_);\\n ensureNonzeroAddress(riskFund_);\\n\\n __Ownable2Step_init();\\n\\n protocolIncome = protocolIncome_;\\n riskFund = riskFund_;\\n }\\n\\n /**\\n * @notice 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 address oldPoolRegistry = poolRegistry;\\n poolRegistry = poolRegistry_;\\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\\n }\\n\\n /**\\n * @notice Release funds\\n * @param comptroller Pool's Comptroller\\n * @param asset Asset to be released\\n * @param amount Amount to release\\n * @return Number of total released tokens\\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\\n */\\n function releaseFunds(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external nonReentrant returns (uint256) {\\n ensureNonzeroAddress(asset);\\n require(amount <= _poolsAssetsReserves[comptroller][asset], \\\"ProtocolShareReserve: Insufficient pool balance\\\");\\n\\n assetsReserves[asset] -= amount;\\n _poolsAssetsReserves[comptroller][asset] -= amount;\\n uint256 protocolIncomeAmount = mul_(\\n Exp({ mantissa: amount }),\\n div_(Exp({ mantissa: PROTOCOL_SHARE_PERCENTAGE * EXP_SCALE }), BASE_UNIT)\\n ).mantissa;\\n\\n address riskFund_ = riskFund;\\n\\n emit FundsReleased(comptroller, asset, amount);\\n\\n IERC20Upgradeable(asset).safeTransfer(protocolIncome, protocolIncomeAmount);\\n IERC20Upgradeable(asset).safeTransfer(riskFund_, amount - protocolIncomeAmount);\\n\\n // Update the pool asset's state in the risk fund for the above transfer.\\n IRiskFund(riskFund_).updateAssetsState(comptroller, asset);\\n\\n return amount;\\n }\\n\\n /**\\n * @notice 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 */\\n function updateAssetsState(address comptroller, address asset)\\n public\\n override(IProtocolShareReserve, ReserveHelpers)\\n {\\n super.updateAssetsState(comptroller, asset);\\n }\\n}\\n\",\"keccak256\":\"0x871a26ce46666f37ff88034dec23d0bb9497b057a861bfd35b166a3ea3e4c785\",\"license\":\"BSD-3-Clause\"},\"contracts/RiskFund/ReserveHelpers.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\n\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\nimport { ComptrollerInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\n\\ncontract ReserveHelpers is Ownable2StepUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 private constant NOT_ENTERED = 1;\\n\\n uint256 private constant ENTERED = 2;\\n\\n // Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools).\\n mapping(address => uint256) public assetsReserves;\\n\\n // Store the asset's reserve per pool in the ProtocolShareReserve.\\n // Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) internal _poolsAssetsReserves;\\n\\n // Address of pool registry contract\\n address public poolRegistry;\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n uint256 internal status;\\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 */\\n uint256[46] private __gap;\\n\\n /// @notice Event emitted after the update of the assets reserves.\\n /// @param comptroller Pool's Comptroller address\\n /// @param asset Token address\\n /// @param amount An amount by which the reserves have increased\\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice event emitted on sweep token success\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(status != ENTERED, \\\"re-entered\\\");\\n status = ENTERED;\\n _;\\n status = NOT_ENTERED;\\n }\\n\\n /**\\n * @notice A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input\\n * @param _token The address of the BEP-20 token to sweep\\n * @param _to Recipient of the output tokens.\\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\\n * @custom:access Only Owner\\n */\\n function sweepToken(address _token, address _to) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(_to);\\n uint256 balanceDfference_;\\n uint256 balance_ = IERC20Upgradeable(_token).balanceOf(address(this));\\n\\n require(balance_ > assetsReserves[_token], \\\"ReserveHelpers: Zero surplus tokens\\\");\\n unchecked {\\n balanceDfference_ = balance_ - assetsReserves[_token];\\n }\\n\\n emit SweepToken(_token, _to, balanceDfference_);\\n IERC20Upgradeable(_token).safeTransfer(_to, balanceDfference_);\\n }\\n\\n /**\\n * @notice 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 Asset's reserve in risk fund.\\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\\n */\\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256) {\\n ensureNonzeroAddress(asset);\\n require(ComptrollerInterface(comptroller).isComptroller(), \\\"ReserveHelpers: Comptroller address invalid\\\");\\n return _poolsAssetsReserves[comptroller][asset];\\n }\\n\\n /**\\n * @notice 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 * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\\n */\\n function updateAssetsState(address comptroller, address asset) public virtual {\\n ensureNonzeroAddress(asset);\\n require(ComptrollerInterface(comptroller).isComptroller(), \\\"ReserveHelpers: Comptroller address invalid\\\");\\n address poolRegistry_ = poolRegistry;\\n require(poolRegistry_ != address(0), \\\"ReserveHelpers: Pool Registry address is not set\\\");\\n require(\\n PoolRegistryInterface(poolRegistry_).getVTokenForAsset(comptroller, asset) != address(0),\\n \\\"ReserveHelpers: The pool doesn't support the asset\\\"\\n );\\n\\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\\n uint256 assetReserve = assetsReserves[asset];\\n if (currentBalance > assetReserve) {\\n uint256 balanceDifference;\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n assetsReserves[asset] += balanceDifference;\\n _poolsAssetsReserves[comptroller][asset] += balanceDifference;\\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x689e7d9481b9a86b421de41ad87459e92146c5f2e00ac041b853ee3ad14e4bdf\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { IProtocolShareReserve } from \\\"./RiskFund/IProtocolShareReserve.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\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 /**\\n * @notice Construct a new money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\n );\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n _borrowFresh(msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return amount The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(address account)\\n external\\n view\\n override\\n returns (\\n uint256 error,\\n uint256 vTokenBalance,\\n uint256 borrowBalance,\\n uint256 exchangeRate\\n )\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return rate The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this v\\n * @return rate The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number */\\n uint256 currentBlockNumber = _getBlockNumber();\\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is sending the assets for supply\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n */\\n function _mintFresh(\\n address payer,\\n address minter,\\n uint256 mintAmount\\n ) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `_doTransferIn` for the minter and the mintAmount.\\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n }\\n\\n /**\\n * @notice User redeems vTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n */\\n function _redeemFresh(\\n address redeemer,\\n uint256 redeemTokensIn,\\n uint256 redeemAmountIn\\n ) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\\n * On success, the vToken has redeemAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(redeemer, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrower User who borrows the assets\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the borrower and the borrowAmount.\\n * On success, the vToken borrowAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(borrower, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call _doTransferIn for the payer and the repayAmount\\n * On success, the vToken holds an additional repayAmount of cash.\\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == NO_ERROR, \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n */\\n function _seize(\\n address seizerContract,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n uint256 totalReservesNew = totalReserves + protocolSeizeAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalReserves = totalReservesNew;\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), protocolSeizeTokens);\\n emit ReservesAdded(address(this), protocolSeizeAmount, totalReservesNew);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(address(comptroller), underlying);\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetInterestRateModelFreshCheck();\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\\n * This function returns the actual amount received,\\n * which may be less than `amount` if there is a fee attached to the transfer.\\n * @param from Sender of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n * @return Actual amount received\\n */\\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n // Return the amount that was *actually* transferred\\n return balanceAfter - balanceBefore;\\n }\\n\\n /**\\n * @dev Just a regular ERC-20 transfer, reverts on failure\\n * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n */\\n function _transferTokens(\\n address spender,\\n address src,\\n address dst,\\n uint256 tokens\\n ) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n _setComptroller(comptroller_);\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = _getBlockNumber();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying tokens owned by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n return token.balanceOf(address(this));\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n * @return Current block number\\n */\\n function _getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0x90ec54cadfdd13bc09a1bc4ae1cc37585b695804a6c95d8b42fb866ec269a300\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\n\\n // Maximum borrow rate that can ever be applied (.0005% / block)\\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\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\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address indexed admin, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account)\\n external\\n view\\n virtual\\n returns (\\n uint256,\\n uint256,\\n uint256,\\n uint256\\n );\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe82d0de552cfda8da11191a3b0bd24d5e218f182d1fdb776585b97cf27c5f4de\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev The approximate number of blocks per year that is assumed by the interest rate model\\nuint256 constant BLOCKS_PER_YEAR = 10_512_000;\\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\",\"keccak256\":\"0x04cd899695ea593a2529cb6a1a04c2a34bff0c1516bd70a5f638ae7a850cad8b\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x909eb76841ebd57d8f53686b76b1a09da7bbbbcddb29510c41674d5aa84c713e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061001961001e565b6100dd565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146100db576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611480806100ec6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80637b77cd6a11610097578063aac59a7511610066578063aac59a75146101ed578063afcff50f14610200578063e30c397814610213578063f2fde38b1461022457600080fd5b80637b77cd6a146101a35780637cf89030146101b65780638bbdf2af146101c95780638da5cb5b146101dc57600080fd5b8063485cc955116100d3578063485cc9551461016d5780636fb0527514610180578063715018a61461019357806379ba50971461019b57600080fd5b80630e3e3e3a146100fa578063258836fe1461012a578063439b55171461013f575b600080fd5b60c95461010d906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61013d6101383660046111c0565b610237565b005b61015f61014d3660046111f9565b60976020526000908152604090205481565b604051908152602001610121565b61013d61017b3660046111c0565b6103ea565b61015f61018e3660046111c0565b61053f565b61013d6105f3565b61013d610607565b61013d6101b13660046111f9565b610681565b60ca5461010d906001600160a01b031681565b61015f6101d7366004611216565b6106e4565b6033546001600160a01b031661010d565b61013d6101fb3660046111c0565b610968565b60995461010d906001600160a01b031681565b6065546001600160a01b031661010d565b61013d6102323660046111f9565b610976565b61023f6109e7565b6002609a54036102835760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b60448201526064015b60405180910390fd5b6002609a5561029181610a41565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156102da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102fe9190611257565b6001600160a01b03851660009081526097602052604090205490915081116103745760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b606482015260840161027a565b6001600160a01b038481166000818152609760209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36103df6001600160a01b0385168484610a68565b50506001609a555050565b600054610100900460ff161580801561040a5750600054600160ff909116105b806104245750303b158015610424575060005460ff166001145b6104875760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161027a565b6000805460ff1916600117905580156104aa576000805461ff0019166101001790555b6104b383610a41565b6104bc82610a41565b6104c4610aba565b60c980546001600160a01b038086166001600160a01b03199283161790925560ca805492851692909116919091179055801561053a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600061054a82610a41565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab9190611270565b6105c75760405162461bcd60e51b815260040161027a90611292565b506001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b6105fb6109e7565b6106056000610ae9565b565b60655433906001600160a01b031681146106755760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161027a565b61067e81610ae9565b50565b6106896109e7565b61069281610a41565b609980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b60006002609a54036107255760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015260640161027a565b6002609a5561073383610a41565b6001600160a01b038085166000908152609860209081526040808320938716835292905220548211156107c05760405162461bcd60e51b815260206004820152602f60248201527f50726f746f636f6c5368617265526573657276653a20496e737566666963696560448201526e6e7420706f6f6c2062616c616e636560881b606482015260840161027a565b6001600160a01b038316600090815260976020526040812080548492906107e89084906112f3565b90915550506001600160a01b038085166000908152609860209081526040808320938716835292905290812080548492906108249084906112f3565b92505081905550600061087060405180602001604052808581525061086b6040518060200160405280670de0b6b3a76400006032610862919061130a565b90526064610b02565b610b33565b5160ca546040518581529192506001600160a01b0390811691868216918816907feed10c470424824e4a4309075162f10b9989088b23fbed2349698cedd44493fb9060200160405180910390a360c9546108d7906001600160a01b03878116911684610a68565b6108f6816108e584876112f3565b6001600160a01b0388169190610a68565b60405163aac59a7560e01b81526001600160a01b038781166004830152868116602483015282169063aac59a7590604401600060405180830381600087803b15801561094157600080fd5b505af1158015610955573d6000803e3d6000fd5b50506001609a5550939695505050505050565b6109728282610b72565b5050565b61097e6109e7565b606580546001600160a01b0383166001600160a01b031990911681179091556109af6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146106055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161027a565b6001600160a01b03811661067e576040516342bcdf7f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261053a908490610ea5565b600054610100900460ff16610ae15760405162461bcd60e51b815260040161027a90611329565b610605610f7a565b606580546001600160a01b031916905561067e81610faa565b6040805160208101909152600081526040518060200160405280610b2a856000015185610ffc565b90529392505050565b6040805160208101909152600081526040518060200160405280670de0b6b3a7640000610b688660000151866000015161100f565b610b2a9190611374565b610b7b81610a41565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdc9190611270565b610bf85760405162461bcd60e51b815260040161027a90611292565b6099546001600160a01b031680610c6a5760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b606482015260840161027a565b60405163266e0a7f60e01b81526001600160a01b03848116600483015283811660248301526000919083169063266e0a7f90604401602060405180830381865afa158015610cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce09190611396565b6001600160a01b031603610d515760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b606482015260840161027a565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbc9190611257565b6001600160a01b03841660009081526097602052604090205490915080821115610e9e576001600160a01b0384166000908152609760205260408120805483850392839291610e0c9084906113b3565b90915550506001600160a01b03808716600090815260986020908152604080832093891683529290529081208054839290610e489084906113b3565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce3883604051610e9491815260200190565b60405180910390a3505b5050505050565b6000610efa826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661101b9092919063ffffffff16565b9050805160001480610f1b575080806020019051810190610f1b9190611270565b61053a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161027a565b600054610100900460ff16610fa15760405162461bcd60e51b815260040161027a90611329565b61060533610ae9565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006110088284611374565b9392505050565b6000611008828461130a565b606061102a8484600085611032565b949350505050565b6060824710156110935760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161027a565b600080866001600160a01b031685876040516110af91906113fb565b60006040518083038185875af1925050503d80600081146110ec576040519150601f19603f3d011682016040523d82523d6000602084013e6110f1565b606091505b50915091506111028783838761110d565b979650505050505050565b6060831561117c578251600003611175576001600160a01b0385163b6111755760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161027a565b508161102a565b61102a83838151156111915781518083602001fd5b8060405162461bcd60e51b815260040161027a9190611417565b6001600160a01b038116811461067e57600080fd5b600080604083850312156111d357600080fd5b82356111de816111ab565b915060208301356111ee816111ab565b809150509250929050565b60006020828403121561120b57600080fd5b8135611008816111ab565b60008060006060848603121561122b57600080fd5b8335611236816111ab565b92506020840135611246816111ab565b929592945050506040919091013590565b60006020828403121561126957600080fd5b5051919050565b60006020828403121561128257600080fd5b8151801515811461100857600080fd5b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082821015611305576113056112dd565b500390565b6000816000190483118215151615611324576113246112dd565b500290565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008261139157634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156113a857600080fd5b8151611008816111ab565b600082198211156113c6576113c66112dd565b500190565b60005b838110156113e65781810151838201526020016113ce565b838111156113f5576000848401525b50505050565b6000825161140d8184602087016113cb565b9190910192915050565b60208152600082518060208401526114368160408501602087016113cb565b601f01601f1916919091016040019291505056fea26469706673582212203e243cb1b5d00b5ce8fca153bc592828d0668926156305aabe1b7e91490ff94664736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c80637b77cd6a11610097578063aac59a7511610066578063aac59a75146101ed578063afcff50f14610200578063e30c397814610213578063f2fde38b1461022457600080fd5b80637b77cd6a146101a35780637cf89030146101b65780638bbdf2af146101c95780638da5cb5b146101dc57600080fd5b8063485cc955116100d3578063485cc9551461016d5780636fb0527514610180578063715018a61461019357806379ba50971461019b57600080fd5b80630e3e3e3a146100fa578063258836fe1461012a578063439b55171461013f575b600080fd5b60c95461010d906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61013d6101383660046111c0565b610237565b005b61015f61014d3660046111f9565b60976020526000908152604090205481565b604051908152602001610121565b61013d61017b3660046111c0565b6103ea565b61015f61018e3660046111c0565b61053f565b61013d6105f3565b61013d610607565b61013d6101b13660046111f9565b610681565b60ca5461010d906001600160a01b031681565b61015f6101d7366004611216565b6106e4565b6033546001600160a01b031661010d565b61013d6101fb3660046111c0565b610968565b60995461010d906001600160a01b031681565b6065546001600160a01b031661010d565b61013d6102323660046111f9565b610976565b61023f6109e7565b6002609a54036102835760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b60448201526064015b60405180910390fd5b6002609a5561029181610a41565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156102da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102fe9190611257565b6001600160a01b03851660009081526097602052604090205490915081116103745760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b606482015260840161027a565b6001600160a01b038481166000818152609760209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36103df6001600160a01b0385168484610a68565b50506001609a555050565b600054610100900460ff161580801561040a5750600054600160ff909116105b806104245750303b158015610424575060005460ff166001145b6104875760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161027a565b6000805460ff1916600117905580156104aa576000805461ff0019166101001790555b6104b383610a41565b6104bc82610a41565b6104c4610aba565b60c980546001600160a01b038086166001600160a01b03199283161790925560ca805492851692909116919091179055801561053a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600061054a82610a41565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab9190611270565b6105c75760405162461bcd60e51b815260040161027a90611292565b506001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b6105fb6109e7565b6106056000610ae9565b565b60655433906001600160a01b031681146106755760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161027a565b61067e81610ae9565b50565b6106896109e7565b61069281610a41565b609980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b60006002609a54036107255760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015260640161027a565b6002609a5561073383610a41565b6001600160a01b038085166000908152609860209081526040808320938716835292905220548211156107c05760405162461bcd60e51b815260206004820152602f60248201527f50726f746f636f6c5368617265526573657276653a20496e737566666963696560448201526e6e7420706f6f6c2062616c616e636560881b606482015260840161027a565b6001600160a01b038316600090815260976020526040812080548492906107e89084906112f3565b90915550506001600160a01b038085166000908152609860209081526040808320938716835292905290812080548492906108249084906112f3565b92505081905550600061087060405180602001604052808581525061086b6040518060200160405280670de0b6b3a76400006032610862919061130a565b90526064610b02565b610b33565b5160ca546040518581529192506001600160a01b0390811691868216918816907feed10c470424824e4a4309075162f10b9989088b23fbed2349698cedd44493fb9060200160405180910390a360c9546108d7906001600160a01b03878116911684610a68565b6108f6816108e584876112f3565b6001600160a01b0388169190610a68565b60405163aac59a7560e01b81526001600160a01b038781166004830152868116602483015282169063aac59a7590604401600060405180830381600087803b15801561094157600080fd5b505af1158015610955573d6000803e3d6000fd5b50506001609a5550939695505050505050565b6109728282610b72565b5050565b61097e6109e7565b606580546001600160a01b0383166001600160a01b031990911681179091556109af6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146106055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161027a565b6001600160a01b03811661067e576040516342bcdf7f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261053a908490610ea5565b600054610100900460ff16610ae15760405162461bcd60e51b815260040161027a90611329565b610605610f7a565b606580546001600160a01b031916905561067e81610faa565b6040805160208101909152600081526040518060200160405280610b2a856000015185610ffc565b90529392505050565b6040805160208101909152600081526040518060200160405280670de0b6b3a7640000610b688660000151866000015161100f565b610b2a9190611374565b610b7b81610a41565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdc9190611270565b610bf85760405162461bcd60e51b815260040161027a90611292565b6099546001600160a01b031680610c6a5760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b606482015260840161027a565b60405163266e0a7f60e01b81526001600160a01b03848116600483015283811660248301526000919083169063266e0a7f90604401602060405180830381865afa158015610cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce09190611396565b6001600160a01b031603610d515760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b606482015260840161027a565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbc9190611257565b6001600160a01b03841660009081526097602052604090205490915080821115610e9e576001600160a01b0384166000908152609760205260408120805483850392839291610e0c9084906113b3565b90915550506001600160a01b03808716600090815260986020908152604080832093891683529290529081208054839290610e489084906113b3565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce3883604051610e9491815260200190565b60405180910390a3505b5050505050565b6000610efa826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661101b9092919063ffffffff16565b9050805160001480610f1b575080806020019051810190610f1b9190611270565b61053a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161027a565b600054610100900460ff16610fa15760405162461bcd60e51b815260040161027a90611329565b61060533610ae9565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006110088284611374565b9392505050565b6000611008828461130a565b606061102a8484600085611032565b949350505050565b6060824710156110935760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161027a565b600080866001600160a01b031685876040516110af91906113fb565b60006040518083038185875af1925050503d80600081146110ec576040519150601f19603f3d011682016040523d82523d6000602084013e6110f1565b606091505b50915091506111028783838761110d565b979650505050505050565b6060831561117c578251600003611175576001600160a01b0385163b6111755760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161027a565b508161102a565b61102a83838151156111915781518083602001fd5b8060405162461bcd60e51b815260040161027a9190611417565b6001600160a01b038116811461067e57600080fd5b600080604083850312156111d357600080fd5b82356111de816111ab565b915060208301356111ee816111ab565b809150509250929050565b60006020828403121561120b57600080fd5b8135611008816111ab565b60008060006060848603121561122b57600080fd5b8335611236816111ab565b92506020840135611246816111ab565b929592945050506040919091013590565b60006020828403121561126957600080fd5b5051919050565b60006020828403121561128257600080fd5b8151801515811461100857600080fd5b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082821015611305576113056112dd565b500390565b6000816000190483118215151615611324576113246112dd565b500290565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008261139157634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156113a857600080fd5b8151611008816111ab565b600082198211156113c6576113c66112dd565b500190565b60005b838110156113e65781810151838201526020016113ce565b838111156113f5576000848401525b50505050565b6000825161140d8184602087016113cb565b9190910192915050565b60208152600082518060208401526114368160408501602087016113cb565b601f01601f1916919091016040019291505056fea26469706673582212203e243cb1b5d00b5ce8fca153bc592828d0668926156305aabe1b7e91490ff94664736f6c634300080d0033", - "devdoc": { - "kind": "dev", - "methods": { - "acceptOwnership()": { - "details": "The new owner accepts the ownership transfer." - }, - "constructor": { - "custom:oz-upgrades-unsafe-allow": "constructor" - }, - "getPoolAssetReserve(address,address)": { - "custom:error": "ZeroAddressNotAllowed is thrown when asset address is zero", - "params": { - "asset": "Asset address.", - "comptroller": "Comptroller address(pool)." - }, - "returns": { - "_0": "Asset's reserve in risk fund." - } - }, - "initialize(address,address)": { - "custom:error": "ZeroAddressNotAllowed is thrown when protocol income address is zeroZeroAddressNotAllowed is thrown when risk fund address is zero", - "params": { - "protocolIncome_": "The address protocol income will be sent to", - "riskFund_": "Risk fund address" - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "pendingOwner()": { - "details": "Returns the address of the pending owner." - }, - "releaseFunds(address,address,uint256)": { - "custom:error": "ZeroAddressNotAllowed is thrown when asset address is zero", - "params": { - "amount": "Amount to release", - "asset": "Asset to be released", - "comptroller": "Pool's Comptroller" - }, - "returns": { - "_0": "Number of total released tokens" - } - }, - "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." - }, - "setPoolRegistry(address)": { - "custom:error": "ZeroAddressNotAllowed is thrown when pool registry address is zero", - "params": { - "poolRegistry_": "Address of the pool registry" - } - }, - "sweepToken(address,address)": { - "custom:access": "Only Owner", - "custom:error": "ZeroAddressNotAllowed is thrown when asset address is zero", - "params": { - "_to": "Recipient of the output tokens.", - "_token": "The address of the BEP-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)": { - "params": { - "asset": "Asset address.", - "comptroller": "Comptroller address(pool)" - } - } - }, - "version": 1 - }, - "userdoc": { - "errors": { - "ZeroAddressNotAllowed()": [ - { - "notice": "Thrown if the supplied address is a zero address where it is not allowed" - } - ] - }, - "events": { - "AssetsReservesUpdated(address,address,uint256)": { - "notice": "Event emitted after the update of the assets reserves." - }, - "FundsReleased(address,address,uint256)": { - "notice": "Emitted when funds are released" - }, - "PoolRegistryUpdated(address,address)": { - "notice": "Emitted when pool registry address is updated" - }, - "SweepToken(address,address,uint256)": { - "notice": "event emitted on sweep token success" - } - }, - "kind": "user", - "methods": { - "getPoolAssetReserve(address,address)": { - "notice": "Get the Amount of the asset in the risk fund for the specific pool." - }, - "initialize(address,address)": { - "notice": "Initializes the deployer to owner." - }, - "releaseFunds(address,address,uint256)": { - "notice": "Release funds" - }, - "setPoolRegistry(address)": { - "notice": "Pool registry setter." - }, - "sweepToken(address,address)": { - "notice": "A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input" - }, - "updateAssetsState(address,address)": { - "notice": "Update the reserve of the asset for the specific pool after transferring to the protocol share reserve." - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 290, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 293, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 1397, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 162, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 282, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 71, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_pendingOwner", - "offset": 0, - "slot": "101", - "type": "t_address" - }, - { - "astId": 150, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "__gap", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 13338, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "assetsReserves", - "offset": 0, - "slot": "151", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 13344, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_poolsAssetsReserves", - "offset": 0, - "slot": "152", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 13346, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "poolRegistry", - "offset": 0, - "slot": "153", - "type": "t_address" - }, - { - "astId": 13349, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "status", - "offset": 0, - "slot": "154", - "type": "t_uint256" - }, - { - "astId": 13354, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "__gap", - "offset": 0, - "slot": "155", - "type": "t_array(t_uint256)46_storage" - }, - { - "astId": 13101, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "protocolIncome", - "offset": 0, - "slot": "201", - "type": "t_address" - }, - { - "astId": 13103, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "riskFund", - "offset": 0, - "slot": "202", - "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_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/RewardsDistributor_DeFi_2.json b/deployments/bscmainnet/RewardsDistributor_DeFi_2.json new file mode 100644 index 000000000..bf2d03909 --- /dev/null +++ b/deployments/bscmainnet/RewardsDistributor_DeFi_2.json @@ -0,0 +1,1270 @@ +{ + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "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": [ + { + "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": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAccrued", + "type": "uint256" + } + ], + "name": "ContributorRewardsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketInitialized", + "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": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "RewardTokenBorrowIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardTokenGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "RewardTokenSupplyIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenSupplySpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "SupplyLastRewardingBlockUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "INITIAL_INDEX", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "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": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "distributeBorrowerRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", + "type": "address" + } + ], + "name": "distributeSupplierRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "grantRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract Comptroller", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "initializeMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastContributorBlock", + "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": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenContributorSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardTokenSpeed", + "type": "uint256" + } + ], + "name": "setContributorRewardTokenSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" + } + ], + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "setRewardTokenSpeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + } + ], + "name": "updateContributorRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updateRewardTokenSupplyIndex", + "outputs": [], + "stateMutability": "nonpayable", + "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": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "transactionIndex": 123, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000808000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000002000001000008000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000010000000000000000000000084040000000000800000000000000000000000002000000400000000000008800000000000000000000000000020000000000000000001040000000200000400080000000000000020002000000200000000000000000000000000000800000000000000000000000000", + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53", + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "logs": [ + { + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000001251d4ef6bb9f56c8bef7d3a201f00f4c122589" + ], + "data": "0x", + "logIndex": 294, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" + }, + { + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" + ], + "data": "0x", + "logIndex": 295, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" + }, + { + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 296, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" + }, + { + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 297, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" + }, + { + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 298, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" + }, + { + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006beb6d2695b67feb73ad4f172e8e2975497187e4", + "logIndex": 299, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" + } + ], + "blockNumber": 33136375, + "cumulativeGasUsed": "11315130", + "status": 1, + "byzantium": true + }, + "args": [ + "0x01251D4eF6bb9f56C8Bef7D3A201f00f4C122589", + "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", + "0xbe2030940000000000000000000000003344417c9360b963ca93a4e8305361aede340ab900000000000000000000000055d398326f99059ff775485246999027b319795500000000000000000000000000000000000000000000000000000000000000640000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555" + ], + "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": [ + "0x3344417c9360b963ca93A4e8305361AEde340Ab9", + "0x55d398326f99059fF775485246999027B3197955", + 100, + "0x4788629ABc6cFCA10F9f969efdEAa1cF70c23555" + ] + }, + "implementation": "0x01251D4eF6bb9f56C8Bef7D3A201f00f4C122589", + "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/bscmainnet/ProtocolShareReserve_Proxy.json b/deployments/bscmainnet/RewardsDistributor_DeFi_2_Proxy.json similarity index 93% rename from deployments/bscmainnet/ProtocolShareReserve_Proxy.json rename to deployments/bscmainnet/RewardsDistributor_DeFi_2_Proxy.json index 7540804c1..3d4dc6240 100644 --- a/deployments/bscmainnet/ProtocolShareReserve_Proxy.json +++ b/deployments/bscmainnet/RewardsDistributor_DeFi_2_Proxy.json @@ -1,5 +1,5 @@ { - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", "abi": [ { "inputs": [ @@ -146,74 +146,94 @@ "type": "receive" } ], - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", "receipt": { "to": null, - "from": "0x55A9f5374Af30E3045FB491f1da3C2E8a74d168D", - "contractAddress": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", - "transactionIndex": 111, - "gasUsed": "817682", - "logsBloom": "0x00000000010000000000000000000000400000000000000000800000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000002000001000000000000000000000000000000010000020000000000000000000800000000800000000000000000000000400001800000080000000000000000000000000000000080000000000000800000000000000000000000000000000400000000000000000000000000000002000000000020000000000000000000040000000000000400000000000000001020000000000000000000000000000000000000000000000000000000000000000100", - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112", - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "transactionIndex": 123, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000808000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000002000001000008000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000010000000000000000000000084040000000000800000000000000000000000002000000400000000000008800000000000000000000000000020000000000000000001040000000200000400080000000000000020002000000200000000000000000000000000000800000000000000000000000000", + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53", + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", "logs": [ { - "transactionIndex": 111, - "blockNumber": 31670925, - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", - "0x000000000000000000000000c1c56732fcafca0f66d59745ec69dc642ec20ab8" + "0x00000000000000000000000001251d4ef6bb9f56c8bef7d3a201f00f4c122589" ], "data": "0x", - "logIndex": 258, - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112" + "logIndex": 294, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" }, { - "transactionIndex": 111, - "blockNumber": 31670925, - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000055a9f5374af30e3045fb491f1da3c2e8a74d168d" + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" ], "data": "0x", - "logIndex": 259, - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112" + "logIndex": 295, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" }, { - "transactionIndex": 111, - "blockNumber": 31670925, - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 296, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" + }, + { + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 297, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" + }, + { + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 260, - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112" + "logIndex": 298, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" }, { - "transactionIndex": 111, - "blockNumber": 31670925, - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "transactionIndex": 123, + "blockNumber": 33136375, + "transactionHash": "0xc8b227c3ab5d2c866878675f8ba4d9192d0df9192fa8c6f6c0eaee3b8202f12c", + "address": "0xD86FCff6CCF5C4E277E49e1dC01Ed4bcAb8260ba", "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006beb6d2695b67feb73ad4f172e8e2975497187e4", - "logIndex": 261, - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112" + "logIndex": 299, + "blockHash": "0x9916532be8cc7bbc57a83b20e200a2e05c1ada0ab8bed0eb64856bb55649bb53" } ], - "blockNumber": 31670925, - "cumulativeGasUsed": "13118645", + "blockNumber": 33136375, + "cumulativeGasUsed": "11315130", "status": 1, "byzantium": true }, "args": [ - "0xc1c56732FcaFca0F66D59745Ec69DC642EC20ab8", + "0x01251D4eF6bb9f56C8Bef7D3A201f00f4C122589", "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", - "0x485cc955000000000000000000000000f322942f644a996a617bd29c16bd7d231d9f35e9000000000000000000000000df31a28d68a2ab381d42b380649ead7ae2a76e42" + "0xbe2030940000000000000000000000003344417c9360b963ca93a4e8305361aede340ab900000000000000000000000055d398326f99059ff775485246999027b319795500000000000000000000000000000000000000000000000000000000000000640000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555" ], "numDeployments": 1, "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", diff --git a/deployments/bscmainnet/VToken_vPLANET_DeFi.json b/deployments/bscmainnet/VToken_vPLANET_DeFi.json new file mode 100644 index 000000000..e7836ae71 --- /dev/null +++ b/deployments/bscmainnet/VToken_vPLANET_DeFi.json @@ -0,0 +1,246 @@ +{ + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "transactionIndex": 89, + "gasUsed": "691318", + "logsBloom": "0x00000000000400000000001000000000000001000000000000808000020000000000000000000040080000020000000000000000000800000000000840008000001000000000000000000000001000000001000000000000000000000000002000002000020004000080000000000800000002000000000000000000000000408000000000000010000000000000080200000000080080140000000000000000000000000000020100000000000400000000000000800000000000008000004000000004010000000002000080040040000000000000080000a00000000020000040000000000000000000800000000400000800000000000040000000010000", + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b", + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "logs": [ + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000002b8a1c539abac89cbf7e2bc6987a0a38a5e660d4" + ], + "data": "0x", + "logIndex": 293, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + }, + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" + ], + "data": "0x", + "logIndex": 294, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + }, + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 295, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + }, + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000003344417c9360b963ca93a4e8305361aede340ab9" + ], + "data": "0x", + "logIndex": 296, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + }, + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000053dbe3c0d1bd439e4f600ad36791c41d02906e6b" + ], + "data": "0x", + "logIndex": 297, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + }, + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003782dace9d90000", + "logIndex": 298, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + }, + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000f37530a8a810fcb501aa0ecd0b0699388f0f2209" + ], + "data": "0x", + "logIndex": 299, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + }, + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000ca01d5a9a248a830e9d93231e791b1affed7c446" + ], + "data": "0x", + "logIndex": 300, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + }, + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10", + "0x000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab6396" + ], + "data": "0x", + "logIndex": 301, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + }, + { + "transactionIndex": 89, + "blockNumber": 33162936, + "transactionHash": "0xa3461e1251566b14e04f1c4dfbc24863b36f58c54993f9f3dd8a59c9837b4760", + "address": "0xFf1112ba7f88a53D4D23ED4e14A117A2aE17C6be", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 302, + "blockHash": "0xac79a3f068df7e3ac8cba8669d914544f2960ccd705a450078bca52d64a0c80b" + } + ], + "blockNumber": 33162936, + "cumulativeGasUsed": "18090956", + "status": 1, + "byzantium": true + }, + "args": [ + "0x2b8A1C539ABaC89CbF7E2Bc6987A0A38A5e660D4", + "0x8a42c319000000000000000000000000ca6d678e74f553f0e59cccc03ae644a3c2c5ee7d0000000000000000000000003344417c9360b963ca93a4e8305361aede340ab900000000000000000000000053dbe3c0d1bd439e4f600ad36791c41d02906e6b0000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab63960000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555000000000000000000000000f37530a8a810fcb501aa0ecd0b0699388f0f2209000000000000000000000000ca01d5a9a248a830e9d93231e791b1affed7c44600000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000001356656e757320504c414e45542028446546692900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c76504c414e45545f446546690000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "82cd33260a9b17bbce6d70381b9dc2d8", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/bsctestnet.json b/deployments/bsctestnet.json index a1bb7c019..263dd11be 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -2907,8 +2907,8 @@ } ] }, - "JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink5000bps": { - "address": "0x9d812A63A5e33f2fC54810f71466FeD862A5eF28", + "JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps": { + "address": "0xb7C5A751CCa00b11AF3CA4A35e9e992f0f9c9c9c", "abi": [ { "inputs": [ @@ -3208,8 +3208,8 @@ } ] }, - "JumpRateModelV2_base200bps_slope500bps_jump25000bps_kink6000bps": { - "address": "0x870BF9ba9b371297F4637f0686468E9a60cF5F12", + "JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink5000bps": { + "address": "0x9d812A63A5e33f2fC54810f71466FeD862A5eF28", "abi": [ { "inputs": [ @@ -3509,8 +3509,8 @@ } ] }, - "JumpRateModelV2_base300bps_slope1000bps_jump25000bps_kink6000bps": { - "address": "0x94d2E7Afb4ACe29D50f12BdfD35858D888e5fEA1", + "JumpRateModelV2_base200bps_slope500bps_jump25000bps_kink6000bps": { + "address": "0x870BF9ba9b371297F4637f0686468E9a60cF5F12", "abi": [ { "inputs": [ @@ -3810,8 +3810,8 @@ } ] }, - "JumpRateModelV2_base350bps_slope1000bps_jump30000bps_kink8000bps": { - "address": "0xC59C757D88c38F9d6B15FDae8D7026D694d1c4E5", + "JumpRateModelV2_base300bps_slope1000bps_jump25000bps_kink6000bps": { + "address": "0x94d2E7Afb4ACe29D50f12BdfD35858D888e5fEA1", "abi": [ { "inputs": [ @@ -4111,94 +4111,108 @@ } ] }, - "MockALPACA": { - "address": "0x6923189d91fdF62dBAe623a55273F1d20306D9f2", + "JumpRateModelV2_base350bps_slope1000bps_jump30000bps_kink8000bps": { + "address": "0xC59C757D88c38F9d6B15FDae8D7026D694d1c4E5", "abi": [ { "inputs": [ { - "internalType": "string", - "name": "name_", - "type": "string" + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" }, { - "internalType": "string", - "name": "symbol_", - "type": "string" + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" }, { - "internalType": "uint8", - "name": "decimals_", - "type": "uint8" + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "owner", + "name": "sender", "type": "address" }, { - "indexed": true, "internalType": "address", - "name": "spender", + "name": "calledContract", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "name": "Approval", - "type": "event" + "name": "Unauthorized", + "type": "error" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" }, { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "value", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", "type": "uint256" } ], - "name": "Transfer", + "name": "NewInterestParams", "type": "event" }, { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, + "inputs": [], + "name": "accessControlManager", + "outputs": [ { - "internalType": "address", - "name": "spender", + "internalType": "contract IAccessControlManagerV8", + "name": "", "type": "address" } ], - "name": "allowance", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", "outputs": [ { "internalType": "uint256", @@ -4212,54 +4226,32 @@ { "inputs": [ { - "internalType": "address", - "name": "spender", - "type": "address" + "internalType": "uint256", + "name": "cash", + "type": "uint256" }, { "internalType": "uint256", - "name": "amount", + "name": "borrows", "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, { "internalType": "uint256", - "name": "", + "name": "badDebt", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", + "name": "getBorrowRate", "outputs": [ { - "internalType": "uint8", + "internalType": "uint256", "name": "", - "type": "uint8" + "type": "uint256" } ], "stateMutability": "view", @@ -4268,54 +4260,45 @@ { "inputs": [ { - "internalType": "address", - "name": "spender", - "type": "address" + "internalType": "uint256", + "name": "cash", + "type": "uint256" }, { "internalType": "uint256", - "name": "subtractedValue", + "name": "borrows", "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ + }, { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, { "internalType": "uint256", - "name": "amount", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", "type": "uint256" } ], - "name": "faucet", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, + "name": "getSupplyRate", + "outputs": [ { "internalType": "uint256", - "name": "addedValue", + "name": "", "type": "uint256" } ], - "name": "increaseAllowance", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", "outputs": [ { "internalType": "bool", @@ -4323,17 +4306,17 @@ "type": "bool" } ], - "stateMutability": "nonpayable", + "stateMutability": "pure", "type": "function" }, { "inputs": [], - "name": "name", + "name": "jumpMultiplierPerBlock", "outputs": [ { - "internalType": "string", + "internalType": "uint256", "name": "", - "type": "string" + "type": "uint256" } ], "stateMutability": "view", @@ -4341,12 +4324,12 @@ }, { "inputs": [], - "name": "symbol", + "name": "kink", "outputs": [ { - "internalType": "string", + "internalType": "uint256", "name": "", - "type": "string" + "type": "uint256" } ], "stateMutability": "view", @@ -4354,7 +4337,7 @@ }, { "inputs": [], - "name": "totalSupply", + "name": "multiplierPerBlock", "outputs": [ { "internalType": "uint256", @@ -4368,60 +4351,378 @@ { "inputs": [ { - "internalType": "address", - "name": "to", - "type": "address" + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" }, { "internalType": "uint256", - "name": "amount", + "name": "multiplierPerYear", "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ + }, { - "internalType": "bool", - "name": "", - "type": "bool" + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" } ], + "name": "updateJumpRateModel", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "from", - "type": "address" + "internalType": "uint256", + "name": "cash", + "type": "uint256" }, { - "internalType": "address", - "name": "to", - "type": "address" + "internalType": "uint256", + "name": "borrows", + "type": "uint256" }, { "internalType": "uint256", - "name": "amount", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", "type": "uint256" } ], - "name": "transferFrom", + "name": "utilizationRate", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], - "stateMutability": "nonpayable", + "stateMutability": "pure", "type": "function" } ] }, - "MockANGLE": { - "address": "0xD1Bc731d188ACc3f52a6226B328a89056B0Ec71a", + "MockALPACA": { + "address": "0x6923189d91fdF62dBAe623a55273F1d20306D9f2", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "MockANGLE": { + "address": "0xD1Bc731d188ACc3f52a6226B328a89056B0Ec71a", "abi": [ { "inputs": [ @@ -7510,6 +7811,315 @@ } ] }, + "MockPLANET": { + "address": "0x52b4E1A2ba407813F829B4b3943A1e57768669A9", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, "MockRACA": { "address": "0xD60cC803d888A3e743F21D0bdE4bF2cAfdEA1F26", "abi": [ @@ -8128,6 +8738,315 @@ } ] }, + "MockSnBNB": { + "address": "0xd2aF6A916Bc77764dc63742BC30f71AF4cF423F4", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, "MockUSDD": { "address": "0x2E2466e22FcbE0732Be385ee2FBb9C59a1098382", "abi": [ @@ -12717,160 +13636,143 @@ } ] }, - "ProtocolShareReserve": { - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "RewardsDistributorImpl": { + "address": "0xfAE44cf6309598c2557Bb265BF0401D594db97DA", "abi": [ { - "anonymous": false, + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" }, { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "MaxLoopsLimitExceeded", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "sender", "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "calledContract", "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "admin", - "outputs": [ + }, { - "internalType": "address", - "name": "admin_", - "type": "address" + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "Unauthorized", + "type": "error" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newAdmin", + "name": "vToken", "type": "address" - } - ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "implementation", - "outputs": [ + }, { - "internalType": "address", - "name": "implementation_", - "type": "address" + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "contributor", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" } ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "contributor", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint256", + "name": "rewardAccrued", + "type": "uint256" } ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" + "name": "ContributorRewardsUpdated", + "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, - "internalType": "address", - "name": "comptroller", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "asset", + "name": "borrower", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", "type": "uint256" } ], - "name": "AssetsReservesUpdated", + "name": "DistributedBorrowerRewardToken", "type": "event" }, { @@ -12878,24 +13780,36 @@ "inputs": [ { "indexed": true, - "internalType": "address", - "name": "comptroller", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "asset", + "name": "supplier", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", "type": "uint256" } ], - "name": "FundsReleased", + "name": "DistributedSupplierRewardToken", "type": "event" }, { @@ -12917,17 +13831,49 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketInitialized", + "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": true, + "indexed": false, "internalType": "address", - "name": "newOwner", + "name": "newAccessControlManager", "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "NewAccessControlManager", "type": "event" }, { @@ -12946,7 +13892,7 @@ "type": "address" } ], - "name": "OwnershipTransferred", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -12955,17 +13901,17 @@ { "indexed": true, "internalType": "address", - "name": "oldPoolRegistry", + "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "newPoolRegistry", + "name": "newOwner", "type": "address" } ], - "name": "PoolRegistryUpdated", + "name": "OwnershipTransferred", "type": "event" }, { @@ -12974,101 +13920,123 @@ { "indexed": true, "internalType": "address", - "name": "token", + "name": "vToken", "type": "address" }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "RewardTokenBorrowIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, - "internalType": "address", - "name": "to", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "newSpeed", "type": "uint256" } ], - "name": "SweepToken", + "name": "RewardTokenBorrowSpeedUpdated", "type": "event" }, { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "recipient", "type": "address" - } - ], - "name": "assetsReserves", - "outputs": [ + }, { + "indexed": false, "internalType": "uint256", - "name": "", + "name": "amount", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "RewardTokenGranted", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", + "name": "vToken", "type": "address" } ], - "name": "getPoolAssetReserve", - "outputs": [ + "name": "RewardTokenSupplyIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, { + "indexed": false, "internalType": "uint256", - "name": "", + "name": "newSpeed", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "RewardTokenSupplySpeedUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "protocolIncome_", + "name": "vToken", "type": "address" }, { - "internalType": "address", - "name": "riskFund_", - "type": "address" + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SupplyLastRewardingBlockUpdated", + "type": "event" }, { "inputs": [], - "name": "owner", + "name": "INITIAL_INDEX", "outputs": [ { - "internalType": "address", + "internalType": "uint224", "name": "", - "type": "address" + "type": "uint224" } ], "stateMutability": "view", @@ -13076,10 +14044,17 @@ }, { "inputs": [], - "name": "pendingOwner", + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -13088,75 +14063,92 @@ "type": "function" }, { - "inputs": [], - "name": "poolRegistry", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "holder", "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" } ], - "stateMutability": "view", + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "protocolIncome", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "holder", "type": "address" } ], - "stateMutability": "view", + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" }, { "internalType": "address", - "name": "asset", + "name": "borrower", "type": "address" }, { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "releaseFunds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" } ], + "name": "distributeBorrowerRewardToken", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "renounceOwnership", + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", + "type": "address" + } + ], + "name": "distributeSupplierRewardToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "riskFund", + "name": "getBlockNumber", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", @@ -13166,11 +14158,16 @@ "inputs": [ { "internalType": "address", - "name": "poolRegistry_", + "name": "recipient", "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "setPoolRegistry", + "name": "grantRewardToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -13178,17 +14175,27 @@ { "inputs": [ { - "internalType": "address", - "name": "_token", + "internalType": "contract Comptroller", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", "type": "address" }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + }, { "internalType": "address", - "name": "_to", + "name": "accessControlManager_", "type": "address" } ], - "name": "sweepToken", + "name": "initialize", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -13197,11 +14204,11 @@ "inputs": [ { "internalType": "address", - "name": "newOwner", + "name": "vToken", "type": "address" } ], - "name": "transferOwnership", + "name": "initializeMarket", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -13210,206 +14217,169 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" - }, + } + ], + "name": "lastContributorBlock", + "outputs": [ { - "internalType": "address", - "name": "asset", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "updateAssetsState", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ { - "internalType": "address", - "name": "_logic", - "type": "address" - }, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ { "internalType": "address", - "name": "admin_", + "name": "", "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" } ], - "stateMutability": "payable", - "type": "constructor" - } - ] - }, - "ProtocolShareReserve_Implementation": { - "address": "0x0Bbea4B14f475bF5eb60Fc2b0Ca90d3d089Ef833", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ + "name": "pendingOwner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", + "name": "", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "AssetsReservesUpdated", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "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": "FundsReleased", - "type": "event" + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "rewardToken", + "outputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" } ], - "name": "Initialized", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "", "type": "address" - }, + } + ], + "name": "rewardTokenAccrued", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "", "type": "address" - }, + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "OwnershipTransferred", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "oldPoolRegistry", + "name": "", "type": "address" + } + ], + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" }, { - "indexed": true, - "internalType": "address", - "name": "newPoolRegistry", - "type": "address" + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" } ], - "name": "PoolRegistryUpdated", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "token", + "name": "", "type": "address" }, { - "indexed": true, "internalType": "address", - "name": "to", + "name": "", "type": "address" - }, + } + ], + "name": "rewardTokenBorrowerIndex", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "", "type": "uint256" } ], - "name": "SweepToken", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -13420,7 +14390,7 @@ "type": "address" } ], - "name": "assetsReserves", + "name": "rewardTokenContributorSpeeds", "outputs": [ { "internalType": "uint256", @@ -13435,16 +14405,16 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" }, { "internalType": "address", - "name": "asset", + "name": "", "type": "address" } ], - "name": "getPoolAssetReserve", + "name": "rewardTokenSupplierIndex", "outputs": [ { "internalType": "uint256", @@ -13459,130 +14429,113 @@ "inputs": [ { "internalType": "address", - "name": "protocolIncome_", - "type": "address" - }, - { - "internalType": "address", - "name": "riskFund_", + "name": "", "type": "address" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", + "name": "rewardTokenSupplySpeeds", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "poolRegistry", + "name": "rewardTokenSupplyState", "outputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "protocolIncome", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "accessControlManager_", "type": "address" } ], - "stateMutability": "view", + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", + "name": "contributor", "type": "address" }, { "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "releaseFunds", - "outputs": [ - { - "internalType": "uint256", - "name": "", + "name": "rewardTokenSpeed", "type": "uint256" } ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", + "name": "setContributorRewardTokenSpeed", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "riskFund", - "outputs": [ + "inputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" } ], - "stateMutability": "view", + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "poolRegistry_", - "type": "address" + "internalType": "uint256", + "name": "limit", + "type": "uint256" } ], - "name": "setPoolRegistry", + "name": "setMaxLoopsLimit", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -13590,17 +14543,22 @@ { "inputs": [ { - "internalType": "address", - "name": "_token", - "type": "address" + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" }, { - "internalType": "address", - "name": "_to", - "type": "address" + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" } ], - "name": "sweepToken", + "name": "setRewardTokenSpeeds", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -13622,46 +14580,58 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", + "name": "contributor", "type": "address" } ], - "name": "updateAssetsState", + "name": "updateContributorRewards", "outputs": [], "stateMutability": "nonpayable", "type": "function" - } - ] - }, - "ProtocolShareReserve_Proxy": { - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", - "abi": [ + }, { "inputs": [ { "internalType": "address", - "name": "_logic", + "name": "vToken", "type": "address" }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "admin_", + "name": "vToken", "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" } ], - "stateMutability": "payable", - "type": "constructor" - }, + "name": "updateRewardTokenSupplyIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "RewardsDistributor_DeFi_0": { + "address": "0x2b67Cfaf28a1aBbBf71fb814Ad384d0C5a98e0F9", + "abi": [ { "anonymous": false, "inputs": [ @@ -13784,16 +14754,6 @@ { "stateMutability": "payable", "type": "receive" - } - ] - }, - "RewardsDistributorImpl": { - "address": "0xfAE44cf6309598c2557Bb265BF0401D594db97DA", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" }, { "inputs": [ @@ -14777,11 +15737,181 @@ "outputs": [], "stateMutability": "nonpayable", "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" } ] }, - "RewardsDistributor_DeFi_0": { + "RewardsDistributor_DeFi_0_Proxy": { "address": "0x2b67Cfaf28a1aBbBf71fb814Ad384d0C5a98e0F9", + "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" + } + ] + }, + "RewardsDistributor_DeFi_1": { + "address": "0x4be90041D1e082EfE3613099aA3b987D9045d718", "abi": [ { "anonymous": false, @@ -15912,8 +17042,8 @@ } ] }, - "RewardsDistributor_DeFi_0_Proxy": { - "address": "0x2b67Cfaf28a1aBbBf71fb814Ad384d0C5a98e0F9", + "RewardsDistributor_DeFi_1_Proxy": { + "address": "0x4be90041D1e082EfE3613099aA3b987D9045d718", "abi": [ { "inputs": [ @@ -16061,8 +17191,8 @@ } ] }, - "RewardsDistributor_DeFi_1": { - "address": "0x4be90041D1e082EfE3613099aA3b987D9045d718", + "RewardsDistributor_DeFi_2": { + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", "abi": [ { "anonymous": false, @@ -17193,8 +18323,8 @@ } ] }, - "RewardsDistributor_DeFi_1_Proxy": { - "address": "0x4be90041D1e082EfE3613099aA3b987D9045d718", + "RewardsDistributor_DeFi_2_Proxy": { + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", "abi": [ { "inputs": [ @@ -25028,8 +26158,8 @@ } ] }, - "RewardsDistributor_StableCoins_0": { - "address": "0xb0269d68CfdCc30Cb7Cd2E0b52b08Fa7Ffd3079b", + "RewardsDistributor_LiquidStakedBNB_4": { + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", "abi": [ { "anonymous": false, @@ -26160,8 +27290,8 @@ } ] }, - "RewardsDistributor_StableCoins_0_Proxy": { - "address": "0xb0269d68CfdCc30Cb7Cd2E0b52b08Fa7Ffd3079b", + "RewardsDistributor_LiquidStakedBNB_4_Proxy": { + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", "abi": [ { "inputs": [ @@ -26309,8 +27439,8 @@ } ] }, - "RewardsDistributor_StableCoins_1": { - "address": "0x2aBEf3602B688493fe698EF11D27DCa43a0CE4BE", + "RewardsDistributor_StableCoins_0": { + "address": "0xb0269d68CfdCc30Cb7Cd2E0b52b08Fa7Ffd3079b", "abi": [ { "anonymous": false, @@ -27441,8 +28571,8 @@ } ] }, - "RewardsDistributor_StableCoins_1_Proxy": { - "address": "0x2aBEf3602B688493fe698EF11D27DCa43a0CE4BE", + "RewardsDistributor_StableCoins_0_Proxy": { + "address": "0xb0269d68CfdCc30Cb7Cd2E0b52b08Fa7Ffd3079b", "abi": [ { "inputs": [ @@ -27590,8 +28720,8 @@ } ] }, - "RewardsDistributor_StableCoins_2": { - "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "RewardsDistributor_StableCoins_1": { + "address": "0x2aBEf3602B688493fe698EF11D27DCa43a0CE4BE", "abi": [ { "anonymous": false, @@ -28722,8 +29852,8 @@ } ] }, - "RewardsDistributor_StableCoins_2_Proxy": { - "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "RewardsDistributor_StableCoins_1_Proxy": { + "address": "0x2aBEf3602B688493fe698EF11D27DCa43a0CE4BE", "abi": [ { "inputs": [ @@ -28871,8 +30001,8 @@ } ] }, - "RewardsDistributor_Tron_0": { - "address": "0x095902273F06eEAC825c3F52dEF44f67a86B31cD", + "RewardsDistributor_StableCoins_2": { + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", "abi": [ { "anonymous": false, @@ -30003,8 +31133,8 @@ } ] }, - "RewardsDistributor_Tron_0_Proxy": { - "address": "0x095902273F06eEAC825c3F52dEF44f67a86B31cD", + "RewardsDistributor_StableCoins_2_Proxy": { + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", "abi": [ { "inputs": [ @@ -30152,8 +31282,8 @@ } ] }, - "RewardsDistributor_Tron_1": { - "address": "0x9A73Ba89f6a95611B46b68241aBEcAF2cD0bd78A", + "RewardsDistributor_Tron_0": { + "address": "0x095902273F06eEAC825c3F52dEF44f67a86B31cD", "abi": [ { "anonymous": false, @@ -31284,8 +32414,8 @@ } ] }, - "RewardsDistributor_Tron_1_Proxy": { - "address": "0x9A73Ba89f6a95611B46b68241aBEcAF2cD0bd78A", + "RewardsDistributor_Tron_0_Proxy": { + "address": "0x095902273F06eEAC825c3F52dEF44f67a86B31cD", "abi": [ { "inputs": [ @@ -31433,8 +32563,8 @@ } ] }, - "RewardsDistributor_Tron_2": { - "address": "0x507401883C2a874D919e78a73dD0cB56f2e7eaD7", + "RewardsDistributor_Tron_1": { + "address": "0x9A73Ba89f6a95611B46b68241aBEcAF2cD0bd78A", "abi": [ { "anonymous": false, @@ -32565,8 +33695,8 @@ } ] }, - "RewardsDistributor_Tron_2_Proxy": { - "address": "0x507401883C2a874D919e78a73dD0cB56f2e7eaD7", + "RewardsDistributor_Tron_1_Proxy": { + "address": "0x9A73Ba89f6a95611B46b68241aBEcAF2cD0bd78A", "abi": [ { "inputs": [ @@ -32714,8 +33844,8 @@ } ] }, - "RewardsDistributor_Tron_3": { - "address": "0x1c50672f4752cc0Ae532D9b93b936C21121Ff08b", + "RewardsDistributor_Tron_2": { + "address": "0x507401883C2a874D919e78a73dD0cB56f2e7eaD7", "abi": [ { "anonymous": false, @@ -33846,8 +34976,8 @@ } ] }, - "RewardsDistributor_Tron_3_Proxy": { - "address": "0x1c50672f4752cc0Ae532D9b93b936C21121Ff08b", + "RewardsDistributor_Tron_2_Proxy": { + "address": "0x507401883C2a874D919e78a73dD0cB56f2e7eaD7", "abi": [ { "inputs": [ @@ -33995,8 +35125,8 @@ } ] }, - "RiskFund": { - "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "RewardsDistributor_Tron_3": { + "address": "0x1c50672f4752cc0Ae532D9b93b936C21121Ff08b", "abi": [ { "anonymous": false, @@ -34121,11 +35251,6 @@ "stateMutability": "payable", "type": "receive" }, - { - "inputs": [], - "name": "ApproveFailed", - "type": "error" - }, { "inputs": [ { @@ -34164,9 +35289,23 @@ "type": "error" }, { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" }, { "anonymous": false, @@ -34174,42 +35313,110 @@ { "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "contributor", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "contributor", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "rewardAccrued", "type": "uint256" } ], - "name": "AssetsReservesUpdated", + "name": "ContributorRewardsUpdated", "type": "event" }, { "anonymous": false, "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, { "indexed": true, "internalType": "address", - "name": "oldConvertibleBaseAsset", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "newConvertibleBaseAsset", + "name": "supplier", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", + "type": "uint256" } ], - "name": "ConvertibleBaseAssetUpdated", + "name": "DistributedSupplierRewardToken", "type": "event" }, { @@ -34229,19 +35436,13 @@ "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "oldMaxLoopsLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newmaxLoopsLimit", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" } ], - "name": "MaxLoopsLimitUpdated", + "name": "MarketInitialized", "type": "event" }, { @@ -34250,17 +35451,17 @@ { "indexed": false, "internalType": "uint256", - "name": "oldMinAmountToConvert", + "name": "oldMaxLoopsLimit", "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "newMinAmountToConvert", + "name": "newmaxLoopsLimit", "type": "uint256" } ], - "name": "MinAmountToConvertUpdated", + "name": "MaxLoopsLimitUpdated", "type": "event" }, { @@ -34326,17 +35527,24 @@ { "indexed": true, "internalType": "address", - "name": "oldPancakeSwapRouter", + "name": "vToken", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newPancakeSwapRouter", - "type": "address" + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" } ], - "name": "PancakeSwapRouterUpdated", + "name": "RewardTokenBorrowIndexUpdated", "type": "event" }, { @@ -34344,18 +35552,18 @@ "inputs": [ { "indexed": true, - "internalType": "address", - "name": "oldPoolRegistry", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newPoolRegistry", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" } ], - "name": "PoolRegistryUpdated", + "name": "RewardTokenBorrowSpeedUpdated", "type": "event" }, { @@ -34364,42 +35572,30 @@ { "indexed": true, "internalType": "address", - "name": "oldShortfallContract", + "name": "recipient", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newShortfallContract", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "ShortfallContractUpdated", + "name": "RewardTokenGranted", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address[]", - "name": "markets", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "amountsOutMin", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalAmount", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" } ], - "name": "SwappedPoolsAssets", + "name": "RewardTokenSupplyIndexUpdated", "type": "event" }, { @@ -34407,24 +35603,18 @@ "inputs": [ { "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "newSpeed", "type": "uint256" } ], - "name": "SweepToken", + "name": "RewardTokenSupplySpeedUpdated", "type": "event" }, { @@ -34433,19 +35623,32 @@ { "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" }, { "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" } ], - "name": "TransferredReserveForAuction", + "name": "SupplyLastRewardingBlockUpdated", "type": "event" }, + { + "inputs": [], + "name": "INITIAL_INDEX", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "acceptOwnership", @@ -34470,67 +35673,84 @@ "inputs": [ { "internalType": "address", - "name": "", + "name": "holder", "type": "address" - } - ], - "name": "assetsReserves", - "outputs": [ + }, { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" } ], - "stateMutability": "view", + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "convertibleBaseAsset", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "holder", "type": "address" } ], - "stateMutability": "view", + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" }, { "internalType": "address", - "name": "asset", + "name": "borrower", "type": "address" - } - ], - "name": "getPoolAssetReserve", - "outputs": [ + }, { - "internalType": "uint256", - "name": "", - "type": "uint256" + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" } ], - "stateMutability": "view", + "name": "distributeBorrowerRewardToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", "type": "address" } ], - "name": "getPoolsBaseAssetReserves", + "name": "distributeSupplierRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", "outputs": [ { "internalType": "uint256", @@ -34545,28 +35765,41 @@ "inputs": [ { "internalType": "address", - "name": "pancakeSwapRouter_", + "name": "recipient", "type": "address" }, { "internalType": "uint256", - "name": "minAmountToConvert_", + "name": "amount", "type": "uint256" - }, + } + ], + "name": "grantRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "internalType": "address", - "name": "convertibleBaseAsset_", + "internalType": "contract Comptroller", + "name": "comptroller_", "type": "address" }, { - "internalType": "address", - "name": "accessControlManager_", + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", "type": "address" }, { "internalType": "uint256", "name": "loopsLimit_", "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" } ], "name": "initialize", @@ -34575,8 +35808,27 @@ "type": "function" }, { - "inputs": [], - "name": "maxLoopsLimit", + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "initializeMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastContributorBlock", "outputs": [ { "internalType": "uint256", @@ -34589,7 +35841,7 @@ }, { "inputs": [], - "name": "minAmountToConvert", + "name": "maxLoopsLimit", "outputs": [ { "internalType": "uint256", @@ -34615,7 +35867,7 @@ }, { "inputs": [], - "name": "pancakeSwapRouter", + "name": "pendingOwner", "outputs": [ { "internalType": "address", @@ -34628,10 +35880,17 @@ }, { "inputs": [], - "name": "pendingOwner", + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rewardToken", "outputs": [ { - "internalType": "address", + "internalType": "contract IERC20Upgradeable", "name": "", "type": "address" } @@ -34640,177 +35899,273 @@ "type": "function" }, { - "inputs": [], - "name": "poolRegistry", - "outputs": [ + "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], + "name": "rewardTokenAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "accessControlManager_", + "name": "", "type": "address" } ], - "name": "setAccessControlManager", - "outputs": [], - "stateMutability": "nonpayable", + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "_convertibleBaseAsset", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", "type": "address" } ], - "name": "setConvertibleBaseAsset", - "outputs": [], - "stateMutability": "nonpayable", + "name": "rewardTokenBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenContributorSpeeds", + "outputs": [ { "internalType": "uint256", - "name": "limit", + "name": "", "type": "uint256" } ], - "name": "setMaxLoopsLimit", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplierIndex", + "outputs": [ { "internalType": "uint256", - "name": "minAmountToConvert_", + "name": "", "type": "uint256" } ], - "name": "setMinAmountToConvert", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "pancakeSwapRouter_", + "name": "", "type": "address" } ], - "name": "setPancakeSwapRouter", - "outputs": [], - "stateMutability": "nonpayable", + "name": "rewardTokenSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "poolRegistry_", + "name": "", "type": "address" } ], - "name": "setPoolRegistry", - "outputs": [], - "stateMutability": "nonpayable", + "name": "rewardTokenSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "shortfallContractAddress_", + "name": "accessControlManager_", "type": "address" } ], - "name": "setShortfallContractAddress", + "name": "setAccessControlManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "shortfall", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "contributor", "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardTokenSpeed", + "type": "uint256" } ], - "stateMutability": "view", + "name": "setContributorRewardTokenSpeed", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address[]", - "name": "markets", + "internalType": "contract VToken[]", + "name": "vTokens", "type": "address[]" }, { - "internalType": "uint256[]", - "name": "amountsOutMin", - "type": "uint256[]" - }, - { - "internalType": "address[][]", - "name": "paths", - "type": "address[][]" + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" } ], - "name": "swapPoolsAssets", - "outputs": [ + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "limit", "type": "uint256" } ], + "name": "setMaxLoopsLimit", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "_token", - "type": "address" + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" }, { - "internalType": "address", - "name": "_to", - "type": "address" + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" } ], - "name": "sweepToken", + "name": "setRewardTokenSpeeds", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -34832,23 +36187,12 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "contributor", "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferReserveForAuction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" } ], + "name": "updateContributorRewards", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -34856,16 +36200,36 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "asset", + "name": "vToken", "type": "address" } ], - "name": "updateAssetsState", + "name": "updateRewardTokenSupplyIndex", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -34893,19 +36257,286 @@ } ] }, - "RiskFund_Implementation": { - "address": "0x665085EcC7bc1B59c9872d030f2Bd6c724739709", + "RewardsDistributor_Tron_3_Proxy": { + "address": "0x1c50672f4752cc0Ae532D9b93b936C21121Ff08b", "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ApproveFailed", - "type": "error" - }, + { + "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" + } + ] + }, + "RiskFund": { + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "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": "ApproveFailed", + "type": "error" + }, { "inputs": [ { @@ -35649,12 +37280,7 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" - } - ] - }, - "RiskFund_Proxy": { - "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", - "abi": [ + }, { "inputs": [ { @@ -35675,308 +37301,52 @@ ], "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" } ] }, - "Shortfall": { - "address": "0x503574a82fE2A9f968d355C8AAc1Ba0481859369", + "RiskFund_Implementation": { + "address": "0x1E7DEC93C77740c2bB46daf87ef42056E388dA14", "abi": [ { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "corePoolComptroller_", "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_", + "name": "vbnb_", "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, { "internalType": "address", - "name": "newAdmin", + "name": "nativeWrapped_", "type": "address" } ], - "name": "changeAdmin", - "outputs": [], "stateMutability": "nonpayable", - "type": "function" + "type": "constructor" }, { "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": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "availableBalance", - "type": "uint256" - } - ], - "name": "InsufficientBalance", + "name": "ApproveFailed", "type": "error" }, { "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "address", - "name": "user", - "type": "address" - }, { "internalType": "uint256", - "name": "owedAmount", + "name": "loopsLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "amount", + "name": "requiredLoops", "type": "uint256" } ], - "name": "InsufficientDebt", + "name": "MaxLoopsLimitExceeded", "type": "error" }, { @@ -36014,44 +37384,20 @@ "name": "comptroller", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - }, { "indexed": true, "internalType": "address", - "name": "highestBidder", + "name": "asset", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "highestBidBps", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "seizedRiskFind", + "name": "amount", "type": "uint256" - }, - { - "indexed": false, - "internalType": "contract VToken[]", - "name": "markets", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "marketDebt", - "type": "uint256[]" } ], - "name": "AuctionClosed", + "name": "AssetsReservesUpdated", "type": "event" }, { @@ -36060,123 +37406,30 @@ { "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "oldConvertibleBaseAsset", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - } - ], - "name": "AuctionRestarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ { "indexed": true, "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "enum Shortfall.AuctionType", - "name": "auctionType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "contract VToken[]", - "name": "markets", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "marketsDebt", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "seizedRiskFund", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startBidBps", - "type": "uint256" - } - ], - "name": "AuctionStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "AuctionsPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "sender", + "name": "newConvertibleBaseAsset", "type": "address" } ], - "name": "AuctionsResumed", + "name": "ConvertibleBaseAssetUpdated", "type": "event" }, { "anonymous": false, "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - }, { "indexed": false, - "internalType": "uint256", - "name": "bidBps", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "bidder", - "type": "address" + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "BidPlaced", + "name": "Initialized", "type": "event" }, { @@ -36185,30 +37438,17 @@ { "indexed": false, "internalType": "uint256", - "name": "oldIncentiveBps", + "name": "oldMaxLoopsLimit", "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "newIncentiveBps", + "name": "newmaxLoopsLimit", "type": "uint256" } ], - "name": "IncentiveBpsUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", + "name": "MaxLoopsLimitUpdated", "type": "event" }, { @@ -36217,17 +37457,17 @@ { "indexed": false, "internalType": "uint256", - "name": "oldMinimumPoolBadDebt", + "name": "oldMinAmountToConvert", "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "newMinimumPoolBadDebt", + "name": "newMinAmountToConvert", "type": "uint256" } ], - "name": "MinimumPoolBadDebtUpdated", + "name": "MinAmountToConvertUpdated", "type": "event" }, { @@ -36253,19 +37493,19 @@ "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "oldNextBidderBlockLimit", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "newNextBidderBlockLimit", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "NextBidderBlockLimitUpdated", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -36284,7 +37524,7 @@ "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "OwnershipTransferred", "type": "event" }, { @@ -36293,17 +37533,17 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "oldPancakeSwapRouter", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "newPancakeSwapRouter", "type": "address" } ], - "name": "OwnershipTransferred", + "name": "PancakeSwapRouterUpdated", "type": "event" }, { @@ -36331,23 +37571,42 @@ { "indexed": true, "internalType": "address", - "name": "token", + "name": "oldShortfallContract", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "user", + "name": "newShortfallContract", "type": "address" + } + ], + "name": "ShortfallContractUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "amountsOutMin", + "type": "uint256[]" }, { "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "totalAmount", "type": "uint256" } ], - "name": "TokenDebtAdded", + "name": "SwappedPoolsAssets", "type": "event" }, { @@ -36362,7 +37621,7 @@ { "indexed": true, "internalType": "address", - "name": "user", + "name": "to", "type": "address" }, { @@ -36372,28 +37631,67 @@ "type": "uint256" } ], - "name": "TokenDebtClaimed", + "name": "SweepToken", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "oldWaitForFirstBidder", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "newWaitForFirstBidder", + "name": "amount", "type": "uint256" } ], - "name": "WaitForFirstBidderUpdated", + "name": "TransferredReserveForAuction", "type": "event" }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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", @@ -36422,46 +37720,11 @@ "type": "address" } ], - "name": "auctions", + "name": "assetsReserves", "outputs": [ { "internalType": "uint256", - "name": "startBlock", - "type": "uint256" - }, - { - "internalType": "enum Shortfall.AuctionType", - "name": "auctionType", - "type": "uint8" - }, - { - "internalType": "enum Shortfall.AuctionStatus", - "name": "status", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "seizedRiskFund", - "type": "uint256" - }, - { - "internalType": "address", - "name": "highestBidder", - "type": "address" - }, - { - "internalType": "uint256", - "name": "highestBidBps", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "highestBidBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "startBidBps", + "name": "", "type": "uint256" } ], @@ -36470,12 +37733,12 @@ }, { "inputs": [], - "name": "auctionsPaused", + "name": "convertibleBaseAsset", "outputs": [ { - "internalType": "bool", + "internalType": "address", "name": "", - "type": "bool" + "type": "address" } ], "stateMutability": "view", @@ -36484,19 +37747,25 @@ { "inputs": [ { - "internalType": "contract IERC20Upgradeable", - "name": "token", + "internalType": "address", + "name": "comptroller", "type": "address" }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPoolAssetReserve", + "outputs": [ { "internalType": "uint256", - "name": "amount_", + "name": "", "type": "uint256" } ], - "name": "claimTokenDebt", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -36507,14 +37776,7 @@ "type": "address" } ], - "name": "closeAuction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "incentiveBps", + "name": "getPoolsBaseAssetReserves", "outputs": [ { "internalType": "uint256", @@ -36528,19 +37790,29 @@ { "inputs": [ { - "internalType": "contract IRiskFund", - "name": "riskFund_", + "internalType": "address", + "name": "pancakeSwapRouter_", "type": "address" }, { "internalType": "uint256", - "name": "minimumPoolBadDebt_", + "name": "minAmountToConvert_", "type": "uint256" }, + { + "internalType": "address", + "name": "convertibleBaseAsset_", + "type": "address" + }, { "internalType": "address", "name": "accessControlManager_", "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" } ], "name": "initialize", @@ -36550,7 +37822,7 @@ }, { "inputs": [], - "name": "minimumPoolBadDebt", + "name": "maxLoopsLimit", "outputs": [ { "internalType": "uint256", @@ -36563,7 +37835,7 @@ }, { "inputs": [], - "name": "nextBidderBlockLimit", + "name": "minAmountToConvert", "outputs": [ { "internalType": "uint256", @@ -36589,14 +37861,7 @@ }, { "inputs": [], - "name": "pauseAuctions", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", + "name": "pancakeSwapRouter", "outputs": [ { "internalType": "address", @@ -36608,26 +37873,16 @@ "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "pendingOwner", + "outputs": [ { "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" - }, - { - "internalType": "uint256", - "name": "bidBps", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" } ], - "name": "placeBid", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -36654,44 +37909,50 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "accessControlManager_", "type": "address" } ], - "name": "restartAuction", + "name": "setAccessControlManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "resumeAuctions", + "inputs": [ + { + "internalType": "address", + "name": "_convertibleBaseAsset", + "type": "address" + } + ], + "name": "setConvertibleBaseAsset", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "riskFund", - "outputs": [ + "inputs": [ { - "internalType": "contract IRiskFund", - "name": "", - "type": "address" + "internalType": "uint256", + "name": "limit", + "type": "uint256" } ], - "stateMutability": "view", + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "accessControlManager_", - "type": "address" + "internalType": "uint256", + "name": "minAmountToConvert_", + "type": "uint256" } ], - "name": "setAccessControlManager", + "name": "setMinAmountToConvert", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -36700,11 +37961,11 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "pancakeSwapRouter_", "type": "address" } ], - "name": "startAuction", + "name": "setPancakeSwapRouter", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -36712,22 +37973,37 @@ { "inputs": [ { - "internalType": "contract IERC20Upgradeable", - "name": "", + "internalType": "address", + "name": "poolRegistry_", "type": "address" - }, + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "", + "name": "shortfallContractAddress_", "type": "address" } ], - "name": "tokenDebt", + "name": "setShortfallContractAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -36736,12 +38012,27 @@ { "inputs": [ { - "internalType": "contract IERC20Upgradeable", - "name": "", - "type": "address" + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amountsOutMin", + "type": "uint256[]" + }, + { + "internalType": "address[][]", + "name": "paths", + "type": "address[][]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "totalTokenDebt", + "name": "swapPoolsAssets", "outputs": [ { "internalType": "uint256", @@ -36749,18 +38040,23 @@ "type": "uint256" } ], - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "newOwner", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", "type": "address" } ], - "name": "transferOwnership", + "name": "sweepToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -36768,39 +38064,37 @@ { "inputs": [ { - "internalType": "uint256", - "name": "_incentiveBps", - "type": "uint256" + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "updateIncentiveBps", + "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, { "internalType": "uint256", - "name": "_minimumPoolBadDebt", + "name": "amount", "type": "uint256" } ], - "name": "updateMinimumPoolBadDebt", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "name": "transferReserveForAuction", + "outputs": [ { "internalType": "uint256", - "name": "_nextBidderBlockLimit", + "name": "", "type": "uint256" } ], - "name": "updateNextBidderBlockLimit", - "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -36808,41 +38102,25 @@ "inputs": [ { "internalType": "address", - "name": "poolRegistry_", + "name": "comptroller", "type": "address" - } - ], - "name": "updatePoolRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, { - "internalType": "uint256", - "name": "_waitForFirstBidder", - "type": "uint256" + "internalType": "address", + "name": "asset", + "type": "address" } ], - "name": "updateWaitForFirstBidder", + "name": "updateAssetsState", "outputs": [], "stateMutability": "nonpayable", "type": "function" - }, - { - "inputs": [], - "name": "waitForFirstBidder", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, + } + ] + }, + "RiskFund_Proxy": { + "address": "0x487CeF72dacABD7E12e633bb3B63815a386f7012", + "abi": [ { "inputs": [ { @@ -36863,142 +38141,152 @@ ], "stateMutability": "payable", "type": "constructor" - } - ] - }, - "Shortfall_Implementation": { - "address": "0x40Ec22d1aA01236dE2FB3dF049DE9f104A25c87C", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "token", + "name": "previousAdmin", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "recipient", + "name": "newAdmin", "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "availableBalance", - "type": "uint256" } ], - "name": "InsufficientBalance", - "type": "error" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "token", + "name": "beacon", "type": "address" - }, + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "user", + "name": "implementation", "type": "address" - }, - { - "internalType": "uint256", - "name": "owedAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "InsufficientDebt", - "type": "error" + "name": "Upgraded", + "type": "event" }, { - "inputs": [ + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ { "internalType": "address", - "name": "sender", + "name": "admin_", "type": "address" - }, + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "calledContract", + "name": "newAdmin", "type": "address" - }, - { - "internalType": "string", - "name": "methodSignature", - "type": "string" } ], - "name": "Unauthorized", - "type": "error" + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "newImplementation", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" - }, + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "indexed": true, "internalType": "address", - "name": "highestBidder", + "name": "newImplementation", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "highestBidBps", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "seizedRiskFind", - "type": "uint256" - }, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "Shortfall": { + "address": "0x503574a82fE2A9f968d355C8AAc1Ba0481859369", + "abi": [ + { + "anonymous": false, + "inputs": [ { "indexed": false, - "internalType": "contract VToken[]", - "name": "markets", - "type": "address[]" + "internalType": "address", + "name": "previousAdmin", + "type": "address" }, { "indexed": false, - "internalType": "uint256[]", - "name": "marketDebt", - "type": "uint256[]" + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "name": "AuctionClosed", + "name": "AdminChanged", "type": "event" }, { @@ -37007,17 +38295,248 @@ { "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "beacon", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "auctionStartBlock", - "type": "uint256" } ], - "name": "AuctionRestarted", + "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": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "availableBalance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "owedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "InsufficientDebt", + "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": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "highestBidder", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "highestBidBps", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizedRiskFind", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract VToken[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "marketDebt", + "type": "uint256[]" + } + ], + "name": "AuctionClosed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" + } + ], + "name": "AuctionRestarted", "type": "event" }, { @@ -37789,12 +39308,7 @@ ], "stateMutability": "view", "type": "function" - } - ] - }, - "Shortfall_Proxy": { - "address": "0x503574a82fE2A9f968d355C8AAc1Ba0481859369", - "abi": [ + }, { "inputs": [ { @@ -37815,391 +39329,357 @@ ], "stateMutability": "payable", "type": "constructor" + } + ] + }, + "Shortfall_Implementation": { + "address": "0x40Ec22d1aA01236dE2FB3dF049DE9f104A25c87C", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "token", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "recipient", "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "availableBalance", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "InsufficientBalance", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "user", "type": "address" + }, + { + "internalType": "uint256", + "name": "owedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "InsufficientDebt", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "name": "Upgraded", - "type": "event" + "name": "Unauthorized", + "type": "error" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" }, { - "inputs": [], - "name": "admin", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "admin_", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "highestBidder", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "highestBidBps", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizedRiskFind", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract VToken[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "marketDebt", + "type": "uint256[]" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "AuctionClosed", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newAdmin", + "name": "comptroller", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" } ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AuctionRestarted", + "type": "event" }, { - "inputs": [], - "name": "implementation", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "implementation_", + "name": "comptroller", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum Shortfall.AuctionType", + "name": "auctionType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "contract VToken[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "marketsDebt", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizedRiskFund", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startBidBps", + "type": "uint256" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "AuctionStarted", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "newImplementation", + "name": "sender", "type": "address" } ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AuctionsPaused", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "newImplementation", + "name": "sender", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" + "name": "AuctionsResumed", + "type": "event" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "SwapRouter_DeFi": { - "address": "0x89Bc8dFe0Af08b60ec285071d133FCdfa9B3C08e", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "WBNB_", + "name": "comptroller", "type": "address" }, { - "internalType": "address", - "name": "factory_", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "auctionStartBlock", + "type": "uint256" }, { - "internalType": "address", - "name": "_comptrollerAddress", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "bidBps", + "type": "uint256" }, { + "indexed": true, "internalType": "address", - "name": "_vBNBAddress", + "name": "bidder", "type": "address" } ], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "BidPlaced", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "oldIncentiveBps", "type": "uint256" }, { + "indexed": false, "internalType": "uint256", - "name": "amountMax", + "name": "newIncentiveBps", "type": "uint256" } ], - "name": "ExcessiveInputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "IdenticalAddresses", - "type": "error" + "name": "IncentiveBpsUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountIntMax", - "type": "uint256" - } - ], - "name": "InputAmountAboveMaximum", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "sweepAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientInputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientOutputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPath", - "type": "error" + "name": "Initialized", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", + "name": "oldMinimumPoolBadDebt", "type": "uint256" - } - ], - "name": "OutputAmountBelowMinimum", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCheck", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "repayer", - "type": "address" - }, - { - "internalType": "address", - "name": "vToken", - "type": "address" }, { + "indexed": false, "internalType": "uint256", - "name": "errorCode", + "name": "newMinimumPoolBadDebt", "type": "uint256" } ], - "name": "RepayError", - "type": "error" - }, - { - "inputs": [], - "name": "SafeApproveFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferBNBFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferFromFailed", - "type": "error" + "name": "MinimumPoolBadDebtUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "supplier", + "name": "oldAccessControlManager", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "vToken", + "name": "newAccessControlManager", "type": "address" - }, - { - "internalType": "uint256", - "name": "errorCode", - "type": "uint256" - } - ], - "name": "SupplyError", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "swapAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" } ], - "name": "SwapAmountLessThanAmountOutMin", - "type": "error" + "name": "NewAccessControlManager", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "uint256", - "name": "deadline", + "name": "oldNextBidderBlockLimit", "type": "uint256" }, { + "indexed": false, "internalType": "uint256", - "name": "timestemp", + "name": "newNextBidderBlockLimit", "type": "uint256" } ], - "name": "SwapDeadlineExpire", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "VTokenNotListed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "underlying", - "type": "address" - } - ], - "name": "VTokenUnderlyingInvalid", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "expectedAdddress", - "type": "address" - }, - { - "internalType": "address", - "name": "passedAddress", - "type": "address" - } - ], - "name": "WrongAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" + "name": "NextBidderBlockLimitUpdated", + "type": "event" }, { "anonymous": false, @@ -38245,86 +39725,17 @@ { "indexed": true, "internalType": "address", - "name": "swapper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "name": "SwapBnbForTokens", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "swapper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "SwapBnbForTokensAtSupportingFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "swapper", + "name": "oldPoolRegistry", "type": "address" }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "name": "SwapTokensForBnb", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ { "indexed": true, "internalType": "address", - "name": "swapper", + "name": "newPoolRegistry", "type": "address" - }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" } ], - "name": "SwapTokensForBnbAtSupportingFee", + "name": "PoolRegistryUpdated", "type": "event" }, { @@ -38333,42 +39744,23 @@ { "indexed": true, "internalType": "address", - "name": "swapper", + "name": "token", "type": "address" }, - { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "name": "SwapTokensForTokens", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ { "indexed": true, "internalType": "address", - "name": "swapper", + "name": "user", "type": "address" }, { - "indexed": true, - "internalType": "address[]", - "name": "path", - "type": "address[]" + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "SwapTokensForTokensAtSupportingFee", + "name": "TokenDebtAdded", "type": "event" }, { @@ -38383,51 +39775,38 @@ { "indexed": true, "internalType": "address", - "name": "to", + "name": "user", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "sweepAmount", + "name": "amount", "type": "uint256" } ], - "name": "SweepToken", + "name": "TokenDebtClaimed", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "oldAddress", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "oldWaitForFirstBidder", + "type": "uint256" }, { - "indexed": true, - "internalType": "address", - "name": "newAddress", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "newWaitForFirstBidder", + "type": "uint256" } ], - "name": "VBNBAddressUpdated", + "name": "WaitForFirstBidderUpdated", "type": "event" }, - { - "inputs": [], - "name": "WBNB", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "acceptOwnership", @@ -38437,10 +39816,10 @@ }, { "inputs": [], - "name": "comptrollerAddress", + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -38449,119 +39828,160 @@ "type": "function" }, { - "inputs": [], - "name": "factory", - "outputs": [ + "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ + "name": "auctions", + "outputs": [ { "internalType": "uint256", - "name": "amountOut", + "name": "startBlock", "type": "uint256" }, + { + "internalType": "enum Shortfall.AuctionType", + "name": "auctionType", + "type": "uint8" + }, + { + "internalType": "enum Shortfall.AuctionStatus", + "name": "status", + "type": "uint8" + }, { "internalType": "uint256", - "name": "reserveIn", + "name": "seizedRiskFund", + "type": "uint256" + }, + { + "internalType": "address", + "name": "highestBidder", + "type": "address" + }, + { + "internalType": "uint256", + "name": "highestBidBps", "type": "uint256" }, { "internalType": "uint256", - "name": "reserveOut", + "name": "highestBidBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startBidBps", "type": "uint256" } ], - "name": "getAmountIn", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "auctionsPaused", "outputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" + "internalType": "bool", + "name": "", + "type": "bool" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" }, { "internalType": "uint256", - "name": "reserveIn", + "name": "amount_", "type": "uint256" - }, + } + ], + "name": "claimTokenDebt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "internalType": "uint256", - "name": "reserveOut", - "type": "uint256" + "internalType": "address", + "name": "comptroller", + "type": "address" } ], - "name": "getAmountOut", + "name": "closeAuction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "incentiveBps", "outputs": [ { "internalType": "uint256", - "name": "amountOut", + "name": "", "type": "uint256" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { "inputs": [ + { + "internalType": "contract IRiskFund", + "name": "riskFund_", + "type": "address" + }, { "internalType": "uint256", - "name": "amountOut", + "name": "minimumPoolBadDebt_", "type": "uint256" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "accessControlManager_", + "type": "address" } ], - "name": "getAmountsIn", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minimumPoolBadDebt", "outputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "nextBidderBlockLimit", + "outputs": [ { "internalType": "uint256", - "name": "amountIn", + "name": "", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "getAmountsOut", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" } ], "stateMutability": "view", @@ -38580,6 +40000,13 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "pauseAuctions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "pendingOwner", @@ -38596,379 +40023,348 @@ { "inputs": [ { - "internalType": "uint256", - "name": "amountA", - "type": "uint256" + "internalType": "address", + "name": "comptroller", + "type": "address" }, { "internalType": "uint256", - "name": "reserveA", + "name": "bidBps", "type": "uint256" }, { "internalType": "uint256", - "name": "reserveB", - "type": "uint256" - } - ], - "name": "quote", - "outputs": [ - { - "internalType": "uint256", - "name": "amountB", + "name": "auctionStartBlock", "type": "uint256" } ], - "stateMutability": "pure", + "name": "placeBid", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "name": "poolRegistry", + "outputs": [ { "internalType": "address", - "name": "_vBNBAddress", + "name": "", "type": "address" } ], - "name": "setVBNBAddress", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "address", - "name": "to", + "name": "comptroller", "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapBNBForExactTokens", + "name": "restartAuction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resumeAuctions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "riskFund", "outputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "contract IRiskFund", + "name": "", + "type": "address" } ], - "stateMutability": "payable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "accessControlManager_", "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapBNBForExactTokensAndRepay", + "name": "setAccessControlManager", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "comptroller", "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapBNBForExactTokensAndSupply", + "name": "startAuction", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "vTokenAddress", + "internalType": "contract IERC20Upgradeable", + "name": "", "type": "address" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenDebt", + "outputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "", "type": "uint256" } ], - "name": "swapBNBForFullTokenDebtAndRepay", - "outputs": [], - "stateMutability": "payable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", + "internalType": "contract IERC20Upgradeable", + "name": "", "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapExactBNBForTokens", + "name": "totalTokenDebt", "outputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "stateMutability": "payable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "newOwner", "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "_incentiveBps", "type": "uint256" } ], - "name": "swapExactBNBForTokensAndRepay", + "name": "updateIncentiveBps", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, { "internalType": "uint256", - "name": "amountOutMin", + "name": "_minimumPoolBadDebt", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + } + ], + "name": "updateMinimumPoolBadDebt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "_nextBidderBlockLimit", "type": "uint256" } ], - "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "name": "updateNextBidderBlockLimit", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "poolRegistry_", "type": "address" - }, + } + ], + "name": "updatePoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "amountOutMin", + "name": "_waitForFirstBidder", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + } + ], + "name": "updateWaitForFirstBidder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "waitForFirstBidder", + "outputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "", "type": "uint256" } ], - "name": "swapExactBNBForTokensAndSupply", - "outputs": [], - "stateMutability": "payable", + "stateMutability": "view", "type": "function" - }, + } + ] + }, + "Shortfall_Proxy": { + "address": "0x503574a82fE2A9f968d355C8AAc1Ba0481859369", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "_logic", "type": "address" }, { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "admin_", + "type": "address" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", - "outputs": [], "stateMutability": "payable", - "type": "function" + "type": "constructor" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "to", + "name": "beacon", "type": "address" - }, + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" } ], - "name": "swapExactBNBForTokensAtSupportingFee", + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", "outputs": [ { - "internalType": "uint256", - "name": "swapAmount", - "type": "uint256" + "internalType": "address", + "name": "admin_", + "type": "address" } ], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "address", - "name": "to", + "name": "newAdmin", "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapExactTokensForBNB", + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", "outputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "address", + "name": "implementation_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -38977,27 +40373,12 @@ { "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "address", + "name": "newImplementation", + "type": "address" } ], - "name": "swapExactTokensForBNBAndRepay", + "name": "upgradeTo", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -39005,86 +40386,76 @@ { "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "newImplementation", + "type": "address" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "swapExactTokensForBNBAndRepayAtSupportingFee", + "name": "upgradeToAndCall", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "SwapRouter_DeFi": { + "address": "0x89Bc8dFe0Af08b60ec285071d133FCdfa9B3C08e", + "abi": [ { "inputs": [ { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" + "internalType": "address", + "name": "WBNB_", + "type": "address" }, { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" + "internalType": "address", + "name": "factory_", + "type": "address" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "_comptrollerAddress", + "type": "address" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" } ], - "name": "swapExactTokensForBNBAndSupply", - "outputs": [], "stateMutability": "nonpayable", - "type": "function" + "type": "constructor" }, { "inputs": [ { "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", + "name": "amount", "type": "uint256" }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "uint256", - "name": "deadline", + "name": "amountMax", "type": "uint256" } ], - "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "ExcessiveInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" }, { "inputs": [ @@ -39095,536 +40466,457 @@ }, { "internalType": "uint256", - "name": "amountOutMin", + "name": "amountIntMax", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, + } + ], + "name": "InputAmountAboveMaximum", + "type": "error" + }, + { + "inputs": [ { "internalType": "uint256", - "name": "deadline", + "name": "sweepAmount", "type": "uint256" - } - ], - "name": "swapExactTokensForBNBAtSupportingFee", - "outputs": [ + }, { "internalType": "uint256", - "name": "swapAmount", + "name": "balance", "type": "uint256" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientOutputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPath", + "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "amountIn", + "name": "amountOut", "type": "uint256" }, { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactTokensForTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "OutputAmountBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCheck", + "type": "error" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "repayer", "type": "address" }, { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "vToken", + "type": "address" }, { "internalType": "uint256", - "name": "deadline", + "name": "errorCode", "type": "uint256" } ], - "name": "swapExactTokensForTokensAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "RepayError", + "type": "error" + }, + { + "inputs": [], + "name": "SafeApproveFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferBNBFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFromFailed", + "type": "error" }, { "inputs": [ { "internalType": "address", - "name": "vTokenAddress", + "name": "supplier", "type": "address" }, { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "internalType": "address", + "name": "vToken", + "type": "address" }, { "internalType": "uint256", - "name": "deadline", + "name": "errorCode", "type": "uint256" } ], - "name": "swapExactTokensForTokensAndRepayAtSupportingFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SupplyError", + "type": "error" }, { "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, { "internalType": "uint256", - "name": "amountIn", + "name": "swapAmount", "type": "uint256" }, { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapExactTokensForTokensAndSupply", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" }, { "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, { "internalType": "uint256", - "name": "amountOutMin", + "name": "deadline", "type": "uint256" }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "uint256", - "name": "deadline", + "name": "timestemp", "type": "uint256" } ], - "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapDeadlineExpire", + "type": "error" }, { "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, { "internalType": "address", - "name": "to", + "name": "vToken", "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapExactTokensForTokensAtSupportingFee", - "outputs": [ + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ { - "internalType": "uint256", - "name": "swapAmount", - "type": "uint256" + "internalType": "address", + "name": "underlying", + "type": "address" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "VTokenUnderlyingInvalid", + "type": "error" }, { "inputs": [ { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "internalType": "address", + "name": "expectedAdddress", + "type": "address" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, + "internalType": "address", + "name": "passedAddress", + "type": "address" + } + ], + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "to", + "name": "previousOwner", "type": "address" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "swapTokensForExactBNB", - "outputs": [ + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "OwnershipTransferred", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" }, { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "swapTokensForExactBNBAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapBnbForTokens", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" }, { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapTokensForExactBNBAndSupply", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapBnbForTokensAtSupportingFee", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" }, { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" }, { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapTokensForExactTokens", - "outputs": [ - { + "indexed": true, "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapTokensForBnb", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "vTokenAddress", + "name": "swapper", "type": "address" }, { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" - }, - { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapTokensForExactTokensAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapTokensForBnbAtSupportingFee", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "vTokenAddress", + "name": "swapper", "type": "address" }, { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" - }, - { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" }, { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "swapTokensForExactTokensAndSupply", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapTokensForTokens", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" }, { + "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" } ], - "name": "swapTokensForFullBNBDebtAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SwapTokensForTokensAtSupportingFee", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "vTokenAddress", + "name": "token", "type": "address" }, { - "internalType": "uint256", - "name": "amountInMax", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" }, { + "indexed": false, "internalType": "uint256", - "name": "deadline", + "name": "sweepAmount", "type": "uint256" } ], - "name": "swapTokensForFullTokenDebtAndRepay", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "SweepToken", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "contract IERC20", - "name": "token", + "indexed": true, + "internalType": "address", + "name": "oldAddress", "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "to", + "name": "newAddress", "type": "address" - }, + } + ], + "name": "VBNBAddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ { - "internalType": "uint256", - "name": "sweepAmount", - "type": "uint256" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "sweepToken", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ { "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "vBNBAddress", + "name": "factory", "outputs": [ { "internalType": "address", @@ -39635,61 +40927,34 @@ "stateMutability": "view", "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "SwapRouter_GameFi": { - "address": "0x5D254Bc7c7f2670395B9E0716C21249083D41a4f", - "abi": [ { "inputs": [ { - "internalType": "address", - "name": "WBNB_", - "type": "address" - }, - { - "internalType": "address", - "name": "factory_", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" }, { - "internalType": "address", - "name": "_comptrollerAddress", - "type": "address" + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" }, - { - "internalType": "address", - "name": "_vBNBAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ { "internalType": "uint256", - "name": "amount", + "name": "reserveOut", "type": "uint256" - }, + } + ], + "name": "getAmountIn", + "outputs": [ { "internalType": "uint256", - "name": "amountMax", + "name": "amountIn", "type": "uint256" } ], - "name": "ExcessiveInputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "IdenticalAddresses", - "type": "error" + "stateMutability": "pure", + "type": "function" }, { "inputs": [ @@ -39700,48 +40965,25 @@ }, { "internalType": "uint256", - "name": "amountIntMax", + "name": "reserveIn", "type": "uint256" - } - ], - "name": "InputAmountAboveMaximum", - "type": "error" - }, - { - "inputs": [ + }, { "internalType": "uint256", - "name": "sweepAmount", + "name": "reserveOut", "type": "uint256" - }, + } + ], + "name": "getAmountOut", + "outputs": [ { "internalType": "uint256", - "name": "balance", + "name": "amountOut", "type": "uint256" } ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientInputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientOutputAmount", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPath", - "type": "error" + "stateMutability": "pure", + "type": "function" }, { "inputs": [ @@ -39751,888 +40993,412 @@ "type": "uint256" }, { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "OutputAmountBelowMinimum", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCheck", - "type": "error" + "name": "getAmountsIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "repayer", - "type": "address" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" }, { - "internalType": "address", - "name": "vToken", - "type": "address" - }, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsOut", + "outputs": [ { - "internalType": "uint256", - "name": "errorCode", - "type": "uint256" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "RepayError", - "type": "error" - }, - { - "inputs": [], - "name": "SafeApproveFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferBNBFailed", - "type": "error" - }, - { - "inputs": [], - "name": "SafeTransferFailed", - "type": "error" + "stateMutability": "view", + "type": "function" }, { "inputs": [], - "name": "SafeTransferFromFailed", - "type": "error" - }, - { - "inputs": [ + "name": "owner", + "outputs": [ { "internalType": "address", - "name": "supplier", + "name": "", "type": "address" - }, + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ { "internalType": "address", - "name": "vToken", + "name": "", "type": "address" - }, - { - "internalType": "uint256", - "name": "errorCode", - "type": "uint256" } ], - "name": "SupplyError", - "type": "error" + "stateMutability": "view", + "type": "function" }, { "inputs": [ { "internalType": "uint256", - "name": "swapAmount", + "name": "amountA", "type": "uint256" }, { "internalType": "uint256", - "name": "amountOutMin", + "name": "reserveA", "type": "uint256" - } - ], - "name": "SwapAmountLessThanAmountOutMin", - "type": "error" - }, - { - "inputs": [ + }, { "internalType": "uint256", - "name": "deadline", + "name": "reserveB", "type": "uint256" - }, + } + ], + "name": "quote", + "outputs": [ { "internalType": "uint256", - "name": "timestemp", + "name": "amountB", "type": "uint256" } ], - "name": "SwapDeadlineExpire", - "type": "error" + "stateMutability": "pure", + "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "VTokenNotListed", - "type": "error" + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "underlying", + "name": "_vBNBAddress", "type": "address" } ], - "name": "VTokenUnderlyingInvalid", - "type": "error" + "name": "setVBNBAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "expectedAdddress", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" }, { - "internalType": "address", - "name": "passedAddress", - "type": "address" - } - ], - "name": "WrongAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "to", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "name": "swapBNBForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "OwnershipTransferred", - "type": "event" + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapBnbForTokens", - "type": "event" + "name": "swapBNBForExactTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapBnbForTokensAtSupportingFee", - "type": "event" + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "swapper", - "type": "address" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" }, { - "indexed": true, "internalType": "address[]", "name": "path", "type": "address[]" }, { - "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokens", + "outputs": [ + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" } ], - "name": "SwapTokensForBnb", - "type": "event" + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { "internalType": "address[]", "name": "path", "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapTokensForBnbAtSupportingFee", - "type": "event" + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { "internalType": "address[]", "name": "path", "type": "address[]" }, { - "indexed": true, - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapTokensForTokens", - "type": "event" + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "swapper", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { "internalType": "address[]", "name": "path", "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "SwapTokensForTokensAtSupportingFee", - "type": "event" + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "token", + "name": "vTokenAddress", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": false, "internalType": "uint256", - "name": "sweepAmount", + "name": "deadline", "type": "uint256" } ], - "name": "SweepToken", - "type": "event" + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "oldAddress", - "type": "address" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": true, "internalType": "address", - "name": "newAddress", + "name": "to", "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "VBNBAddressUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "WBNB", + "name": "swapExactBNBForTokensAtSupportingFee", "outputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "comptrollerAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "factory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveOut", - "type": "uint256" - } - ], - "name": "getAmountIn", - "outputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveIn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveOut", - "type": "uint256" - } - ], - "name": "getAmountOut", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "getAmountsIn", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "name": "getAmountsOut", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "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": "uint256", - "name": "amountA", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveA", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveB", - "type": "uint256" - } - ], - "name": "quote", - "outputs": [ - { - "internalType": "uint256", - "name": "amountB", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vBNBAddress", - "type": "address" - } - ], - "name": "setVBNBAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapBNBForExactTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapBNBForExactTokensAndRepay", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapBNBForExactTokensAndSupply", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapBNBForFullTokenDebtAndRepay", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokens", - "outputs": [ - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAndRepay", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAndRepayAtSupportingFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAndSupply", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "path", - "type": "address[]" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "swapExactBNBForTokensAtSupportingFee", - "outputs": [ - { - "internalType": "uint256", - "name": "swapAmount", - "type": "uint256" - } - ], - "stateMutability": "payable", + "stateMutability": "payable", "type": "function" }, { @@ -41341,8 +42107,8 @@ } ] }, - "SwapRouter_LiquidStakedBNB": { - "address": "0xb16792E90d6478DaBbd0144e13f41CeA21ACE116", + "SwapRouter_GameFi": { + "address": "0x5D254Bc7c7f2670395B9E0716C21249083D41a4f", "abi": [ { "inputs": [ @@ -43041,8 +43807,8 @@ } ] }, - "SwapRouter_StableCoins": { - "address": "0x8Ff3c0a74b4CBD4dFA3A35Cca756490bE351F936", + "SwapRouter_LiquidStakedBNB": { + "address": "0xb16792E90d6478DaBbd0144e13f41CeA21ACE116", "abi": [ { "inputs": [ @@ -44741,8 +45507,8 @@ } ] }, - "SwapRouter_Tron": { - "address": "0x1D8cA5AFB88F07489786A3d2E0FF50F3F9314d97", + "SwapRouter_StableCoins": { + "address": "0x8Ff3c0a74b4CBD4dFA3A35Cca756490bE351F936", "abi": [ { "inputs": [ @@ -46441,383 +47207,283 @@ } ] }, - "VTokenBeacon": { - "address": "0xBF85A90673E61956f8c79b9150BAB7893b791bDd", + "SwapRouter_Tron": { + "address": "0x1D8cA5AFB88F07489786A3d2E0FF50F3F9314d97", "abi": [ { "inputs": [ { "internalType": "address", - "name": "implementation_", + "name": "WBNB_", "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "factory_", "type": "address" }, { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "_comptrollerAddress", "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "_vBNBAddress", "type": "address" } ], - "name": "Upgraded", - "type": "event" + "stateMutability": "nonpayable", + "type": "constructor" }, { - "inputs": [], - "name": "implementation", - "outputs": [ + "inputs": [ { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, { - "internalType": "address", - "name": "", - "type": "address" + "internalType": "uint256", + "name": "amountMax", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "ExcessiveInputAmount", + "type": "error" }, { "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "IdenticalAddresses", + "type": "error" }, { "inputs": [ { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, { - "internalType": "address", - "name": "newImplementation", - "type": "address" + "internalType": "uint256", + "name": "amountIntMax", + "type": "uint256" } ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ] - }, - "VTokenImpl": { - "address": "0x91D2c7BCA6Ea3313E07e0F6B3D0D00c4Fae482df", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "InputAmountAboveMaximum", + "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "actualAddAmount", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", "type": "uint256" } ], - "name": "AddReservesFactorFreshCheck", + "name": "InsufficientBalance", "type": "error" }, { "inputs": [], - "name": "BorrowCashNotAvailable", + "name": "InsufficientInputAmount", "type": "error" }, { "inputs": [], - "name": "BorrowFreshnessCheck", + "name": "InsufficientLiquidity", "type": "error" }, { "inputs": [], - "name": "ForceLiquidateBorrowUnauthorized", + "name": "InsufficientOutputAmount", "type": "error" }, { "inputs": [], - "name": "HealBorrowUnauthorized", + "name": "InvalidPath", "type": "error" }, { "inputs": [ { "internalType": "uint256", - "name": "errorCode", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", "type": "uint256" } ], - "name": "LiquidateAccrueCollateralInterestFailed", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateCloseAmountIsUintMax", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateCloseAmountIsZero", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateCollateralFreshnessCheck", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateFreshnessCheck", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateLiquidatorIsBorrower", - "type": "error" - }, - { - "inputs": [], - "name": "LiquidateSeizeLiquidatorIsBorrower", - "type": "error" - }, - { - "inputs": [], - "name": "MintFreshnessCheck", - "type": "error" - }, - { - "inputs": [], - "name": "ProtocolSeizeShareTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "RedeemFreshnessCheck", - "type": "error" - }, - { - "inputs": [], - "name": "RedeemTransferOutNotPossible", - "type": "error" - }, - { - "inputs": [], - "name": "ReduceReservesCashNotAvailable", - "type": "error" - }, - { - "inputs": [], - "name": "ReduceReservesCashValidation", + "name": "OutputAmountBelowMinimum", "type": "error" }, { "inputs": [], - "name": "ReduceReservesFreshCheck", + "name": "ReentrantCheck", "type": "error" }, { - "inputs": [], - "name": "RepayBorrowFreshnessCheck", + "inputs": [ + { + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RepayError", "type": "error" }, { "inputs": [], - "name": "SetInterestRateModelFreshCheck", + "name": "SafeApproveFailed", "type": "error" }, { "inputs": [], - "name": "SetReserveFactorBoundsCheck", + "name": "SafeTransferBNBFailed", "type": "error" }, { "inputs": [], - "name": "SetReserveFactorFreshCheck", + "name": "SafeTransferFailed", "type": "error" }, { "inputs": [], - "name": "TransferNotAllowed", + "name": "SafeTransferFromFailed", "type": "error" }, { "inputs": [ { "internalType": "address", - "name": "sender", + "name": "supplier", "type": "address" }, { "internalType": "address", - "name": "calledContract", + "name": "vToken", "type": "address" }, { - "internalType": "string", - "name": "methodSignature", - "type": "string" + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" } ], - "name": "Unauthorized", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", + "name": "SupplyError", "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "uint256", - "name": "cashPrior", + "name": "swapAmount", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "interestAccumulated", + "name": "amountOutMin", "type": "uint256" - }, + } + ], + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" + }, + { + "inputs": [ { - "indexed": false, "internalType": "uint256", - "name": "borrowIndex", + "name": "deadline", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "totalBorrows", + "name": "timestemp", "type": "uint256" } ], - "name": "AccrueInterest", - "type": "event" + "name": "SwapDeadlineExpire", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "owner", + "name": "vToken", "type": "address" - }, + } + ], + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ { - "indexed": true, "internalType": "address", - "name": "spender", + "name": "underlying", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "Approval", - "type": "event" + "name": "VTokenUnderlyingInvalid", + "type": "error" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "borrower", + "name": "expectedAdddress", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "badDebtDelta", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "badDebtOld", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "badDebtNew", - "type": "uint256" + "internalType": "address", + "name": "passedAddress", + "type": "address" } ], - "name": "BadDebtIncreased", - "type": "event" + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "badDebtOld", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "badDebtNew", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "BadDebtRecovered", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -46826,29 +47492,17 @@ { "indexed": true, "internalType": "address", - "name": "borrower", + "name": "previousOwner", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "borrowAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "accountBorrows", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalBorrows", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "Borrow", + "name": "OwnershipTransferred", "type": "event" }, { @@ -46857,36 +47511,42 @@ { "indexed": true, "internalType": "address", - "name": "payer", + "name": "swapper", "type": "address" }, { "indexed": true, - "internalType": "address", - "name": "borrower", - "type": "address" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": false, - "internalType": "uint256", - "name": "repayAmount", - "type": "uint256" + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "HealBorrow", + "name": "SwapBnbForTokens", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "Initialized", + "name": "SwapBnbForTokensAtSupportingFee", "type": "event" }, { @@ -46895,35 +47555,42 @@ { "indexed": true, "internalType": "address", - "name": "liquidator", + "name": "swapper", "type": "address" }, { "indexed": true, - "internalType": "address", - "name": "borrower", - "type": "address" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": false, - "internalType": "uint256", - "name": "repayAmount", - "type": "uint256" - }, + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForBnb", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, "internalType": "address", - "name": "vTokenCollateral", + "name": "swapper", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "seizeTokens", - "type": "uint256" + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "LiquidateBorrow", + "name": "SwapTokensForBnbAtSupportingFee", "type": "event" }, { @@ -46932,48 +47599,42 @@ { "indexed": true, "internalType": "address", - "name": "minter", + "name": "swapper", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "mintAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "mintTokens", - "type": "uint256" + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "indexed": false, - "internalType": "uint256", - "name": "accountBalance", - "type": "uint256" + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "Mint", + "name": "SwapTokensForTokens", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "oldAccessControlManager", + "name": "swapper", "type": "address" }, { - "indexed": false, - "internalType": "address", - "name": "newAccessControlManager", - "type": "address" + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "NewAccessControlManager", + "name": "SwapTokensForTokensAtSupportingFee", "type": "event" }, { @@ -46981,18 +47642,24 @@ "inputs": [ { "indexed": true, - "internalType": "contract ComptrollerInterface", - "name": "oldComptroller", + "internalType": "address", + "name": "token", "type": "address" }, { "indexed": true, - "internalType": "contract ComptrollerInterface", - "name": "newComptroller", + "internalType": "address", + "name": "to", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" } ], - "name": "NewComptroller", + "name": "SweepToken", "type": "event" }, { @@ -47000,298 +47667,167 @@ "inputs": [ { "indexed": true, - "internalType": "contract InterestRateModel", - "name": "oldInterestRateModel", + "internalType": "address", + "name": "oldAddress", "type": "address" }, { "indexed": true, - "internalType": "contract InterestRateModel", - "name": "newInterestRateModel", + "internalType": "address", + "name": "newAddress", "type": "address" } ], - "name": "NewMarketInterestRateModel", + "name": "VBNBAddressUpdated", "type": "event" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldProtocolSeizeShareMantissa", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newProtocolSeizeShareMantissa", - "type": "uint256" - } - ], - "name": "NewProtocolSeizeShare", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "oldProtocolShareReserve", - "type": "address" - }, + "inputs": [], + "name": "WBNB", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "newProtocolShareReserve", + "name": "", "type": "address" } ], - "name": "NewProtocolShareReserve", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldReserveFactorMantissa", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newReserveFactorMantissa", - "type": "uint256" - } - ], - "name": "NewReserveFactor", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "oldShortfall", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newShortfall", - "type": "address" - } - ], - "name": "NewShortfallContract", - "type": "event" + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, + "inputs": [], + "name": "factory", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "OwnershipTransferred", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "redeemer", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "redeemAmount", + "name": "reserveIn", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "redeemTokens", + "name": "reserveOut", "type": "uint256" - }, + } + ], + "name": "getAmountIn", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "accountBalance", + "name": "amountIn", "type": "uint256" } ], - "name": "Redeem", - "type": "event" + "stateMutability": "pure", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "payer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "borrower", - "type": "address" - }, - { - "indexed": false, "internalType": "uint256", - "name": "repayAmount", + "name": "amountIn", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "accountBorrows", + "name": "reserveIn", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "totalBorrows", + "name": "reserveOut", "type": "uint256" } ], - "name": "RepayBorrow", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "benefactor", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "addAmount", - "type": "uint256" - }, + "name": "getAmountOut", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "newTotalReserves", + "name": "amountOut", "type": "uint256" } ], - "name": "ReservesAdded", - "type": "event" + "stateMutability": "pure", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, "internalType": "uint256", - "name": "reduceAmount", + "name": "amountOut", "type": "uint256" }, { - "indexed": false, - "internalType": "uint256", - "name": "newTotalReserves", - "type": "uint256" + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "ReservesReduced", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "getAmountsIn", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "name": "SweepToken", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "amountIn", "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" } ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "NO_ERROR", + "name": "getAmountsOut", "outputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], "stateMutability": "view", @@ -47299,17 +47835,10 @@ }, { "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "accessControlManager", + "name": "owner", "outputs": [ { - "internalType": "contract IAccessControlManagerV8", + "internalType": "address", "name": "", "type": "address" } @@ -47319,39 +47848,62 @@ }, { "inputs": [], - "name": "accrualBlockNumber", + "name": "pendingOwner", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "accrueInterest", + "inputs": [ + { + "internalType": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "name": "quote", "outputs": [ { "internalType": "uint256", - "name": "", + "name": "amountB", "type": "uint256" } ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "uint256", - "name": "addAmount", - "type": "uint256" + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" } ], - "name": "addReserves", + "name": "setVBNBAddress", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -47359,396 +47911,520 @@ { "inputs": [ { - "internalType": "address", - "name": "owner", - "type": "address" + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { "internalType": "address", - "name": "spender", + "name": "to", "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "allowance", + "name": "swapBNBForExactTokens", "outputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "stateMutability": "view", + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "spender", + "name": "vTokenAddress", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountOut", "type": "uint256" - } - ], - "name": "approve", - "outputs": [ + }, { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "badDebt", - "outputs": [ + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, { "internalType": "uint256", - "name": "recoveredAmount_", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "name": "badDebtRecovered", + "name": "swapBNBForExactTokensAndSupply", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "owner", + "name": "vTokenAddress", "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "owner", + "name": "to", "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "balanceOfUnderlying", + "name": "swapExactBNBForTokens", "outputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, { "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, { "internalType": "uint256", - "name": "borrowAmount", + "name": "amountOutMin", "type": "uint256" - } - ], - "name": "borrow", - "outputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "nonpayable", + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "account", + "name": "vTokenAddress", "type": "address" - } - ], - "name": "borrowBalanceCurrent", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "nonpayable", + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "account", + "name": "vTokenAddress", "type": "address" - } - ], - "name": "borrowBalanceStored", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { - "inputs": [], - "name": "borrowIndex", - "outputs": [ + "inputs": [ { - "internalType": "uint256", - "name": "", + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "borrowRatePerBlock", - "outputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { - "inputs": [], - "name": "comptroller", - "outputs": [ + "inputs": [ { - "internalType": "contract ComptrollerInterface", - "name": "", + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", + "name": "swapExactBNBForTokensAtSupportingFee", "outputs": [ { - "internalType": "uint8", - "name": "", - "type": "uint8" + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" } ], - "stateMutability": "view", + "stateMutability": "payable", "type": "function" }, { "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "spender", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "subtractedValue", + "name": "deadline", "type": "uint256" } ], - "name": "decreaseAllowance", + "name": "swapExactTokensForBNB", "outputs": [ { - "internalType": "bool", - "name": "", - "type": "bool" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "exchangeRateCurrent", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "amountIn", "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "exchangeRateStored", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactTokensForBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "liquidator", - "type": "address" - }, - { - "internalType": "address", - "name": "borrower", - "type": "address" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" }, { "internalType": "uint256", - "name": "repayAmount", + "name": "amountOutMin", "type": "uint256" }, { - "internalType": "contract VTokenInterface", - "name": "vTokenCollateral", - "type": "address" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "internalType": "bool", - "name": "skipLiquidityCheck", - "type": "bool" + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "name": "forceLiquidateBorrow", + "name": "swapExactTokensForBNBAndRepayAtSupportingFee", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "getAccountSnapshot", - "outputs": [ { "internalType": "uint256", - "name": "error", + "name": "amountIn", "type": "uint256" }, { "internalType": "uint256", - "name": "vTokenBalance", + "name": "amountOutMin", "type": "uint256" }, { - "internalType": "uint256", - "name": "borrowBalance", - "type": "uint256" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { "internalType": "uint256", - "name": "exchangeRate", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactTokensForBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "getCash", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "payer", - "type": "address" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { "internalType": "address", - "name": "borrower", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "repayAmount", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", "type": "uint256" } ], - "name": "healBorrow", - "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "spender", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "addedValue", + "name": "deadline", "type": "uint256" } ], - "name": "increaseAllowance", + "name": "swapExactTokensForTokens", "outputs": [ { - "internalType": "bool", - "name": "", - "type": "bool" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], "stateMutability": "nonpayable", @@ -47758,129 +48434,131 @@ "inputs": [ { "internalType": "address", - "name": "underlying_", - "type": "address" - }, - { - "internalType": "contract ComptrollerInterface", - "name": "comptroller_", - "type": "address" - }, - { - "internalType": "contract InterestRateModel", - "name": "interestRateModel_", + "name": "vTokenAddress", "type": "address" }, { "internalType": "uint256", - "name": "initialExchangeRateMantissa_", + "name": "amountIn", "type": "uint256" }, { - "internalType": "string", - "name": "name_", - "type": "string" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" }, { - "internalType": "string", - "name": "symbol_", - "type": "string" + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { - "internalType": "uint8", - "name": "decimals_", - "type": "uint8" - }, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "admin_", + "name": "vTokenAddress", "type": "address" }, { - "internalType": "address", - "name": "accessControlManager_", - "type": "address" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" }, { - "components": [ - { - "internalType": "address", - "name": "shortfall", - "type": "address" - }, - { - "internalType": "address payable", - "name": "protocolShareReserve", - "type": "address" - } - ], - "internalType": "struct VTokenInterface.RiskManagementInit", - "name": "riskManagement", - "type": "tuple" + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" }, { "internalType": "uint256", - "name": "reserveFactorMantissa_", + "name": "deadline", "type": "uint256" } ], - "name": "initialize", + "name": "swapExactTokensForTokensAndRepayAtSupportingFee", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "interestRateModel", - "outputs": [ + "inputs": [ { - "internalType": "contract InterestRateModel", - "name": "", + "internalType": "address", + "name": "vTokenAddress", "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isVToken", - "outputs": [ + }, { - "internalType": "bool", - "name": "", - "type": "bool" + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], - "stateMutability": "pure", + "name": "swapExactTokensForTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "borrower", + "name": "vTokenAddress", "type": "address" }, { "internalType": "uint256", - "name": "repayAmount", + "name": "amountIn", "type": "uint256" }, { - "internalType": "contract VTokenInterface", - "name": "vTokenCollateral", - "type": "address" - } - ], - "name": "liquidateBorrow", - "outputs": [ + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], + "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -47888,39 +48566,35 @@ "inputs": [ { "internalType": "uint256", - "name": "mintAmount", + "name": "amountIn", "type": "uint256" - } - ], - "name": "mint", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountOutMin", "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "minter", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "mintAmount", + "name": "deadline", "type": "uint256" } ], - "name": "mintBehalf", + "name": "swapExactTokensForTokensAtSupportingFee", "outputs": [ { "internalType": "uint256", - "name": "", + "name": "swapAmount", "type": "uint256" } ], @@ -47928,86 +48602,69 @@ "type": "function" }, { - "inputs": [], - "name": "name", - "outputs": [ + "inputs": [ { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "", + "name": "to", "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "protocolSeizeShareMantissa", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "protocolShareReserve", + "name": "swapTokensForExactBNB", "outputs": [ { - "internalType": "address payable", - "name": "", - "type": "address" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "uint256", - "name": "redeemTokens", + "name": "amountOut", "type": "uint256" - } - ], - "name": "redeem", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", "type": "uint256" } ], + "name": "swapTokensForExactBNBAndRepay", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -48015,37 +48672,26 @@ "inputs": [ { "internalType": "uint256", - "name": "redeemAmount", + "name": "amountOut", "type": "uint256" - } - ], - "name": "redeemUnderlying", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountInMax", "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "reduceAmount", + "name": "deadline", "type": "uint256" } ], - "name": "reduceReserves", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", + "name": "swapTokensForExactBNBAndSupply", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -48054,142 +48700,70 @@ "inputs": [ { "internalType": "uint256", - "name": "repayAmount", + "name": "amountOut", "type": "uint256" - } - ], - "name": "repayBorrow", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountInMax", "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "address", - "name": "borrower", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "repayAmount", + "name": "deadline", "type": "uint256" } ], - "name": "repayBorrowBehalf", + "name": "swapTokensForExactTokens", "outputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" } ], "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "reserveFactorMantissa", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { "internalType": "address", - "name": "liquidator", - "type": "address" - }, - { - "internalType": "address", - "name": "borrower", + "name": "vTokenAddress", "type": "address" }, { "internalType": "uint256", - "name": "seizeTokens", + "name": "amountOut", "type": "uint256" - } - ], - "name": "seize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "accessControlManager_", - "type": "address" - } - ], - "name": "setAccessControlManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract InterestRateModel", - "name": "newInterestRateModel", - "type": "address" - } - ], - "name": "setInterestRateModel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, { "internalType": "uint256", - "name": "newProtocolSeizeShareMantissa_", + "name": "amountInMax", "type": "uint256" - } - ], - "name": "setProtocolSeizeShare", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + }, { - "internalType": "address payable", - "name": "protocolShareReserve_", - "type": "address" - } - ], - "name": "setProtocolShareReserve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "newReserveFactorMantissa", + "name": "deadline", "type": "uint256" } ], - "name": "setReserveFactor", + "name": "swapTokensForExactTokensAndRepay", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -48198,169 +48772,106 @@ "inputs": [ { "internalType": "address", - "name": "shortfall_", - "type": "address" - } - ], - "name": "setShortfallContract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "shortfall", - "outputs": [ - { - "internalType": "address", - "name": "", + "name": "vTokenAddress", "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "supplyRatePerBlock", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountOut", "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Upgradeable", - "name": "token", - "type": "address" - } - ], - "name": "sweepToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalBorrows", - "outputs": [ + }, { "internalType": "uint256", - "name": "", + "name": "amountInMax", "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalBorrowsCurrent", - "outputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], + "name": "swapTokensForExactTokensAndSupply", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "totalReserves", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "amountInMax", "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, { "internalType": "uint256", - "name": "", + "name": "deadline", "type": "uint256" } ], - "stateMutability": "view", + "name": "swapTokensForFullBNBDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "dst", + "name": "vTokenAddress", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "amountInMax", "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ + }, { - "internalType": "bool", - "name": "", - "type": "bool" + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" } ], + "name": "swapTokensForFullTokenDebtAndRepay", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "src", + "internalType": "contract IERC20", + "name": "token", "type": "address" }, { "internalType": "address", - "name": "dst", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "sweepAmount", "type": "uint256" } ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "name": "sweepToken", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -48379,7 +48890,7 @@ }, { "inputs": [], - "name": "underlying", + "name": "vBNBAddress", "outputs": [ { "internalType": "address", @@ -48389,58 +48900,44 @@ ], "stateMutability": "view", "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" } ] }, - "VToken_vALPACA_DeFi": { - "address": "0xb7caC5Ef82cb7f9197ee184779bdc52c5490C02a", + "VTokenBeacon": { + "address": "0xBF85A90673E61956f8c79b9150BAB7893b791bDd", "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "implementation_", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "previousAdmin", + "name": "previousOwner", "type": "address" }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "newOwner", "type": "address" } ], - "name": "BeaconUpgraded", + "name": "OwnershipTransferred", "type": "event" }, { @@ -48457,199 +48954,261 @@ "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vANKR_DeFi": { - "address": "0xb677e080148368EeeE70fA3865d07E92c6500174", - "abi": [ - { - "inputs": [ + "inputs": [], + "name": "implementation", + "outputs": [ { "internalType": "address", - "name": "beacon", + "name": "", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, + "inputs": [], + "name": "owner", + "outputs": [ { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "", "type": "address" } ], - "name": "AdminChanged", - "type": "event" + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "newOwner", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "newImplementation", "type": "address" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ] }, - "VToken_vBNBx_LiquidStakedBNB": { - "address": "0x644A149853E5507AdF3e682218b8AC86cdD62951", + "VTokenImpl": { + "address": "0xcA408D716011169645Aa94ddc5665043C33df814", "abi": [ { - "inputs": [ - { - "internalType": "address", - "name": "beacon", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "stateMutability": "payable", + "inputs": [], + "stateMutability": "nonpayable", "type": "constructor" }, { - "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "actualAddAmount", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "AddReservesFactorFreshCheck", + "type": "error" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" + "inputs": [], + "name": "BorrowCashNotAvailable", + "type": "error" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" + "inputs": [], + "name": "BorrowFreshnessCheck", + "type": "error" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [], + "name": "ForceLiquidateBorrowUnauthorized", + "type": "error" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vBSW_DeFi": { - "address": "0x5e68913fbbfb91af30366ab1B21324410b49a308", - "abi": [ + "inputs": [], + "name": "HealBorrowUnauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "LiquidateAccrueCollateralInterestFailed", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsUintMax", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsZero", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCollateralFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateSeizeLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "MintFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "ProtocolSeizeShareTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemTransferOutNotPossible", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashNotAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashValidation", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RepayBorrowFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetInterestRateModelFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorBoundsCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "TransferNotAllowed", + "type": "error" + }, { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "sender", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" }, { "anonymous": false, "inputs": [ { "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" }, { "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" } ], - "name": "AdminChanged", + "name": "AccrueInterest", "type": "event" }, { @@ -48658,11 +49217,23 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "BeaconUpgraded", + "name": "Approval", "type": "event" }, { @@ -48671,72 +49242,117 @@ { "indexed": true, "internalType": "address", - "name": "implementation", + "name": "borrower", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" } ], - "name": "Upgraded", + "name": "BadDebtIncreased", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" + } + ], + "name": "BadDebtRecovered", + "type": "event" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vBTT_Tron": { - "address": "0x47793540757c6E6D84155B33cd8D9535CFdb9334", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "beacon", + "name": "borrower", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "Borrow", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "previousAdmin", + "name": "payer", "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "newAdmin", + "name": "borrower", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" } ], - "name": "AdminChanged", + "name": "HealBorrow", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "BeaconUpgraded", + "name": "Initialized", "type": "event" }, { @@ -48745,41 +49361,67 @@ { "indexed": true, "internalType": "address", - "name": "implementation", + "name": "liquidator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" } ], - "name": "Upgraded", + "name": "LiquidateBorrow", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vFLOKI_GameFi": { - "address": "0xef470AbC365F88e4582D8027172a392C473A5B53", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "beacon", + "name": "minter", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "Mint", + "type": "event" }, { "anonymous": false, @@ -48787,17 +49429,17 @@ { "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "oldAccessControlManager", "type": "address" }, { "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "newAccessControlManager", "type": "address" } ], - "name": "AdminChanged", + "name": "NewAccessControlManager", "type": "event" }, { @@ -48805,12 +49447,18 @@ "inputs": [ { "indexed": true, - "internalType": "address", - "name": "beacon", + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", "type": "address" } ], - "name": "BeaconUpgraded", + "name": "NewComptroller", "type": "event" }, { @@ -48818,134 +49466,132 @@ "inputs": [ { "indexed": true, - "internalType": "address", - "name": "implementation", + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", "type": "address" } ], - "name": "Upgraded", + "name": "NewMarketInterestRateModel", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vHAY_StableCoins": { - "address": "0x170d3b2da05cc2124334240fB34ad1359e34C562", - "abi": [ - { + "anonymous": false, "inputs": [ { - "internalType": "address", - "name": "beacon", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "oldProtocolSeizeShareMantissa", + "type": "uint256" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "NewProtocolSeizeShare", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "previousAdmin", + "name": "oldProtocolShareReserve", "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "newAdmin", + "name": "newProtocolShareReserve", "type": "address" } ], - "name": "AdminChanged", + "name": "NewProtocolShareReserve", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" } ], - "name": "BeaconUpgraded", + "name": "NewReduceReservesBlockDelta", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" } ], - "name": "Upgraded", + "name": "NewReserveFactor", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vNFT_Tron": { - "address": "0x67cD2A8aFF63C7eBbC7A601506f9Dbb8557d6547", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "beacon", + "name": "oldShortfall", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": true, + "internalType": "address", + "name": "newShortfall", + "type": "address" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "NewShortfallContract", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "previousAdmin", + "name": "previousOwner", "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "newAdmin", + "name": "newOwner", "type": "address" } ], - "name": "AdminChanged", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -48954,11 +49600,17 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", "type": "address" } ], - "name": "BeaconUpgraded", + "name": "OwnershipTransferred", "type": "event" }, { @@ -48967,59 +49619,54 @@ { "indexed": true, "internalType": "address", - "name": "implementation", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "Upgraded", + "name": "ProtocolSeize", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vRACA_GameFi": { - "address": "0x1958035231E125830bA5d17D168cEa07Bb42184a", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "beacon", + "name": "redeemer", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, { "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" }, { "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" } ], - "name": "AdminChanged", + "name": "Redeem", "type": "event" }, { @@ -49028,72 +49675,85 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "payer", "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { "indexed": true, "internalType": "address", - "name": "implementation", + "name": "borrower", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" } ], - "name": "Upgraded", + "name": "RepayBorrow", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vTRX_Tron": { - "address": "0x410286c43a525E1DCC7468a9B091C111C8324cd1", - "abi": [ - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "beacon", + "name": "benefactor", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "ReservesAdded", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "previousAdmin", + "name": "protocolShareReserve", "type": "address" }, { "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" } ], - "name": "AdminChanged", + "name": "SpreadReservesReduced", "type": "event" }, { @@ -49102,11 +49762,11 @@ { "indexed": true, "internalType": "address", - "name": "beacon", + "name": "token", "type": "address" } ], - "name": "BeaconUpgraded", + "name": "SweepToken", "type": "event" }, { @@ -49115,839 +49775,1174 @@ { "indexed": true, "internalType": "address", - "name": "implementation", + "name": "from", "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "Upgraded", + "name": "Transfer", "type": "event" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [], + "name": "NO_ERROR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_DeFi": { - "address": "0xa109DE0abaeefC521Ec29D89eA42E64F37A6882E", - "abi": [ + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { - "inputs": [ + "inputs": [], + "name": "accessControlManager", + "outputs": [ { - "internalType": "address", - "name": "beacon", + "internalType": "contract IAccessControlManagerV8", + "name": "", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "accrueInterest", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "name": "addReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_GameFi": { - "address": "0xdeDf3B2bcF25d0023115fd71a0F8221C91C92B1a", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "owner", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "address", + "name": "spender", + "type": "address" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "spender", "type": "address" }, { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "badDebt", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "internalType": "uint256", + "name": "recoveredAmount_", + "type": "uint256" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "name": "badDebtRecovered", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_LiquidStakedBNB": { - "address": "0xD5b20708d8f0FcA52cb609938D0594C4e32E5DaD", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "owner", "type": "address" - }, + } + ], + "name": "balanceOf", + "outputs": [ { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "owner", "type": "address" - }, + } + ], + "name": "balanceOfUnderlying", + "outputs": [ { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "account", "type": "address" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_StableCoins": { - "address": "0x899dDf81DfbbF5889a16D075c352F2b959Dd24A4", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "account", "type": "address" - }, + } + ], + "name": "borrowBalanceStored", + "outputs": [ { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "borrowIndex", + "outputs": [ { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "comptroller", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", + "internalType": "contract ComptrollerInterface", + "name": "", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "decimals", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "internalType": "uint8", + "name": "", + "type": "uint8" } ], - "name": "Upgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDD_Tron": { - "address": "0xD804F74fe21290d213c46610ab171f7c2EeEBDE7", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "spender", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, + "name": "decreaseAllowance", + "outputs": [ { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "bool", + "name": "", + "type": "bool" } ], - "name": "AdminChanged", - "type": "event" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "stateMutability": "view", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_DeFi": { - "address": "0x80CC30811e362aC9aB857C3d7875CbcCc0b65750", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "liquidator", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "borrower", "type": "address" }, { - "indexed": false, - "internalType": "address", - "name": "newAdmin", + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", "type": "address" + }, + { + "internalType": "bool", + "name": "skipLiquidityCheck", + "type": "bool" } ], - "name": "AdminChanged", - "type": "event" + "name": "forceLiquidateBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "account", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "getAccountSnapshot", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vTokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "stateMutability": "view", + "type": "function" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_GameFi": { - "address": "0x0bFE4e0B8A2a096A27e5B18b078d25be57C08634", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "beacon", - "type": "address" - }, + "inputs": [], + "name": "getCash", + "outputs": [ { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "payer", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "borrower", "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "healBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "spender", "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "increaseAllowance", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "internalType": "bool", + "name": "", + "type": "bool" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "stateMutability": "nonpayable", + "type": "function" }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_LiquidStakedBNB": { - "address": "0x2197d02cC9cd1ad51317A0a85A656a0c82383A7c", - "abi": [ { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "underlying_", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", "type": "address" }, { - "indexed": false, + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { "internalType": "address", - "name": "newAdmin", + "name": "admin_", "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "accessControlManager_", "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "shortfall", + "type": "address" + }, + { + "internalType": "address payable", + "name": "protocolShareReserve", + "type": "address" + } + ], + "internalType": "struct VTokenInterface.RiskManagementInit", + "name": "riskManagement", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa_", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "interestRateModel", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", + "internalType": "contract InterestRateModel", + "name": "", "type": "address" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" + "stateMutability": "view", + "type": "function" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_StableCoins": { - "address": "0x3338988d0beb4419Acb8fE624218754053362D06", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "beacon", - "type": "address" - }, + "inputs": [], + "name": "isVToken", + "outputs": [ { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "bool", + "name": "", + "type": "bool" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "pure", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "borrower", "type": "address" }, { - "indexed": false, - "internalType": "address", - "name": "newAdmin", + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", "type": "address" } ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "liquidateBorrow", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vUSDT_Tron": { - "address": "0x712774CBFFCBD60e9825871CcEFF2F917442b2c3", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "beacon", - "type": "address" - }, + "name": "mint", + "outputs": [ { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "minter", "type": "address" }, { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "name", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" + "internalType": "string", + "name": "", + "type": "string" } ], - "name": "BeaconUpgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "owner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "", "type": "address" } ], - "name": "Upgraded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" }, { - "stateMutability": "payable", - "type": "receive" - } - ] - }, - "VToken_vWBNB_LiquidStakedBNB": { - "address": "0x231dED0Dfc99634e52EE1a1329586bc970d773b3", - "abi": [ + "inputs": [], + "name": "protocolSeizeShareMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "reduceReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { "internalType": "address", - "name": "beacon", + "name": "borrower", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "previousAdmin", + "name": "liquidator", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "borrower", "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" } ], - "name": "AdminChanged", - "type": "event" + "name": "seize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "beacon", + "name": "accessControlManager_", "type": "address" } ], - "name": "BeaconUpgraded", - "type": "event" + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "setInterestRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa_", + "type": "uint256" + } + ], + "name": "setProtocolSeizeShare", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "protocolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "setReserveFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "shortfall_", "type": "address" } ], - "name": "Upgraded", - "type": "event" + "name": "setShortfallContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "stateMutability": "payable", - "type": "fallback" + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" }, { - "stateMutability": "payable", - "type": "receive" + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" } ] }, - "VToken_vWIN_Tron": { - "address": "0xEe543D5de2Dbb5b07675Fc72831A2f1812428393", + "VToken_vALPACA_DeFi": { + "address": "0xb7caC5Ef82cb7f9197ee184779bdc52c5490C02a", "abi": [ { "inputs": [ @@ -50020,8 +51015,8 @@ } ] }, - "VToken_vagEUR_Stablecoins": { - "address": "0x4E1D35166776825402d50AfE4286c500027211D1", + "VToken_vANKR_DeFi": { + "address": "0xb677e080148368EeeE70fA3865d07E92c6500174", "abi": [ { "inputs": [ @@ -50094,8 +51089,8 @@ } ] }, - "VToken_vankrBNB_DeFi": { - "address": "0xe507B30C41E9e375BCe05197c1e09fc9ee40c0f6", + "VToken_vBNBx_LiquidStakedBNB": { + "address": "0x644A149853E5507AdF3e682218b8AC86cdD62951", "abi": [ { "inputs": [ @@ -50168,8 +51163,8 @@ } ] }, - "VToken_vankrBNB_LiquidStakedBNB": { - "address": "0x57a664Dd7f1dE19545fEE9c86C949e3BF43d6D47", + "VToken_vBSW_DeFi": { + "address": "0x5e68913fbbfb91af30366ab1B21324410b49a308", "abi": [ { "inputs": [ @@ -50242,8 +51237,8 @@ } ] }, - "VToken_vstkBNB_LiquidStakedBNB": { - "address": "0x75aa42c832a8911B77219DbeBABBB40040d16987", + "VToken_vBTT_Tron": { + "address": "0x47793540757c6E6D84155B33cd8D9535CFdb9334", "abi": [ { "inputs": [ @@ -50316,9 +51311,25 @@ } ] }, - "BinanceOracle": { - "address": "0xB58BFDCE610042311Dc0e034a80Cc7776c1D68f5", + "VToken_vFLOKI_GameFi": { + "address": "0xef470AbC365F88e4582D8027172a392C473A5B53", "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, { "anonymous": false, "inputs": [ @@ -50369,98 +51380,121 @@ "type": "fallback" }, { - "inputs": [], - "name": "admin", - "outputs": [ - { - "internalType": "address", - "name": "admin_", + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vHAY_StableCoins": { + "address": "0x170d3b2da05cc2124334240fB34ad1359e34C562", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { - "inputs": [], - "name": "implementation", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": false, "internalType": "address", - "name": "implementation_", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "beacon", "type": "address" } ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "implementation", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "name": "upgradeToAndCall", - "outputs": [], + "name": "Upgraded", + "type": "event" + }, + { "stateMutability": "payable", - "type": "function" + "type": "fallback" }, { "stateMutability": "payable", "type": "receive" - }, + } + ] + }, + "VToken_vNFT_Tron": { + "address": "0x67cD2A8aFF63C7eBbC7A601506f9Dbb8557d6547", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "calledContract", + "name": "beacon", "type": "address" }, { - "internalType": "string", - "name": "methodSignature", - "type": "string" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "Unauthorized", - "type": "error" + "stateMutability": "payable", + "type": "constructor" }, { "anonymous": false, "inputs": [ { "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "name": "Initialized", + "name": "AdminChanged", "type": "event" }, { @@ -50468,376 +51502,351 @@ "inputs": [ { "indexed": true, - "internalType": "string", - "name": "asset", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" + "internalType": "address", + "name": "beacon", + "type": "address" } ], - "name": "MaxStalePeriodAdded", + "name": "BeaconUpgraded", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "oldAccessControlManager", - "type": "address" - }, - { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "newAccessControlManager", + "name": "implementation", "type": "address" } ], - "name": "NewAccessControlManager", + "name": "Upgraded", "type": "event" }, { - "anonymous": false, + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vPLANET_DeFi": { + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "abi": [ + { "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "beacon", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "stateMutability": "payable", + "type": "constructor" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "previousOwner", + "name": "previousAdmin", "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newOwner", + "name": "newAdmin", "type": "address" } ], - "name": "OwnershipTransferred", + "name": "AdminChanged", "type": "event" }, { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "accessControlManager", - "outputs": [ + "anonymous": false, + "inputs": [ { - "internalType": "contract IAccessControlManagerV8", - "name": "", + "indexed": true, + "internalType": "address", + "name": "beacon", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "inputs": [], - "name": "getFeedRegistryAddress", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vRACA_GameFi": { + "address": "0x1958035231E125830bA5d17D168cEa07Bb42184a", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "vToken", + "name": "beacon", "type": "address" - } - ], - "name": "getUnderlyingPrice", - "outputs": [ + }, { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "_sidRegistryAddress", + "name": "previousAdmin", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "_accessControlManager", + "name": "newAdmin", "type": "address" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "maxStalePeriod", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { + "indexed": true, "internalType": "address", - "name": "", + "name": "beacon", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vSnBNB_LiquidStakedBNB": { + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "accessControlManager_", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "setAccessControlManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { - "internalType": "string", - "name": "symbol", - "type": "string" + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" }, { - "internalType": "uint256", - "name": "_maxStalePeriod", - "type": "uint256" - } - ], - "name": "setMaxStalePeriod", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "sidRegistryAddress", - "outputs": [ - { + "indexed": false, "internalType": "address", - "name": "", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "beacon", "type": "address" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "inputs": [], - "name": "vBnb", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "inputs": [], - "name": "vai", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vTRX_Tron": { + "address": "0x410286c43a525E1DCC7468a9B091C111C8324cd1", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "_logic", - "type": "address" - }, - { - "internalType": "address", - "name": "admin_", + "name": "beacon", "type": "address" }, { "internalType": "bytes", - "name": "_data", + "name": "data", "type": "bytes" } ], "stateMutability": "payable", "type": "constructor" - } - ] - }, - "BinanceOracle_Implementation": { - "address": "0xCd64844CD0E8E34782cd0d1bF3E537bf7b474FAe", - "abi": [ + }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "vBnbAddress", + "name": "previousAdmin", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "vaiAddress", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "calledContract", + "name": "beacon", "type": "address" - }, - { - "internalType": "string", - "name": "methodSignature", - "type": "string" } ], - "name": "Unauthorized", - "type": "error" + "name": "BeaconUpgraded", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" } ], - "name": "Initialized", + "name": "Upgraded", "type": "event" }, { - "anonymous": false, + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDD_DeFi": { + "address": "0xa109DE0abaeefC521Ec29D89eA42E64F37A6882E", + "abi": [ + { "inputs": [ { - "indexed": true, - "internalType": "string", - "name": "asset", - "type": "string" + "internalType": "address", + "name": "beacon", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "MaxStalePeriodAdded", - "type": "event" + "stateMutability": "payable", + "type": "constructor" }, { "anonymous": false, @@ -50845,17 +51854,17 @@ { "indexed": false, "internalType": "address", - "name": "oldAccessControlManager", + "name": "previousAdmin", "type": "address" }, { "indexed": false, "internalType": "address", - "name": "newAccessControlManager", + "name": "newAdmin", "type": "address" } ], - "name": "NewAccessControlManager", + "name": "AdminChanged", "type": "event" }, { @@ -50864,17 +51873,11 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", + "name": "beacon", "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "BeaconUpgraded", "type": "event" }, { @@ -50883,244 +51886,258 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", + "name": "implementation", "type": "address" } ], - "name": "OwnershipTransferred", + "name": "Upgraded", "type": "event" }, { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, { - "inputs": [], - "name": "accessControlManager", - "outputs": [ - { - "internalType": "contract IAccessControlManagerV8", - "name": "", + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDD_GameFi": { + "address": "0xdeDf3B2bcF25d0023115fd71a0F8221C91C92B1a", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { - "inputs": [], - "name": "getFeedRegistryAddress", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": false, "internalType": "address", - "name": "", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "vToken", + "name": "beacon", "type": "address" } ], - "name": "getUnderlyingPrice", - "outputs": [ + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDD_LiquidStakedBNB": { + "address": "0xD5b20708d8f0FcA52cb609938D0594C4e32E5DaD", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "_sidRegistryAddress", + "name": "beacon", "type": "address" }, { - "internalType": "address", - "name": "_accessControlManager", - "type": "address" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "maxStalePeriod", - "outputs": [ + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, { - "internalType": "uint256", - "name": "", - "type": "uint256" + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { - "inputs": [], - "name": "owner", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "beacon", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDD_StableCoins": { + "address": "0x899dDf81DfbbF5889a16D075c352F2b959Dd24A4", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "accessControlManager_", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "setAccessControlManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { - "internalType": "string", - "name": "symbol", - "type": "string" + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" }, { - "internalType": "uint256", - "name": "_maxStalePeriod", - "type": "uint256" - } - ], - "name": "setMaxStalePeriod", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "sidRegistryAddress", - "outputs": [ - { + "indexed": false, "internalType": "address", - "name": "", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "beacon", "type": "address" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "inputs": [], - "name": "vBnb", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "inputs": [], - "name": "vai", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" } ] }, - "BinanceOracle_Proxy": { - "address": "0xB58BFDCE610042311Dc0e034a80Cc7776c1D68f5", + "VToken_vUSDD_Tron": { + "address": "0xD804F74fe21290d213c46610ab171f7c2EeEBDE7", "abi": [ { "inputs": [ { "internalType": "address", - "name": "_logic", - "type": "address" - }, - { - "internalType": "address", - "name": "admin_", + "name": "beacon", "type": "address" }, { "internalType": "bytes", - "name": "_data", + "name": "data", "type": "bytes" } ], @@ -51177,61 +52194,78 @@ "type": "fallback" }, { - "inputs": [], - "name": "admin", - "outputs": [ + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_DeFi": { + "address": "0x80CC30811e362aC9aB857C3d7875CbcCc0b65750", + "abi": [ + { + "inputs": [ { "internalType": "address", - "name": "admin_", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { - "inputs": [], - "name": "implementation", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": false, "internalType": "address", - "name": "implementation_", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "beacon", "type": "address" } ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "implementation", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "name": "upgradeToAndCall", - "outputs": [], + "name": "Upgraded", + "type": "event" + }, + { "stateMutability": "payable", - "type": "function" + "type": "fallback" }, { "stateMutability": "payable", @@ -51239,9 +52273,25 @@ } ] }, - "BoundValidator": { - "address": "0x2842140e4Ad3a92e9af30e27e290300dd785076d", + "VToken_vUSDT_GameFi": { + "address": "0x0bFE4e0B8A2a096A27e5B18b078d25be57C08634", "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, { "anonymous": false, "inputs": [ @@ -51292,136 +52342,195 @@ "type": "fallback" }, { - "inputs": [], - "name": "admin", - "outputs": [ + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_LiquidStakedBNB": { + "address": "0x2197d02cC9cd1ad51317A0a85A656a0c82383A7c", + "abi": [ + { + "inputs": [ { "internalType": "address", - "name": "admin_", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { - "inputs": [], - "name": "implementation", - "outputs": [ + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, { + "indexed": false, "internalType": "address", - "name": "implementation_", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "beacon", "type": "address" } ], - "name": "upgradeTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "implementation", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "name": "upgradeToAndCall", - "outputs": [], + "name": "Upgraded", + "type": "event" + }, + { "stateMutability": "payable", - "type": "function" + "type": "fallback" }, { "stateMutability": "payable", "type": "receive" - }, + } + ] + }, + "VToken_vUSDT_StableCoins": { + "address": "0x3338988d0beb4419Acb8fE624218754053362D06", + "abi": [ { "inputs": [ { "internalType": "address", - "name": "sender", + "name": "beacon", "type": "address" }, { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, "internalType": "address", - "name": "calledContract", + "name": "previousAdmin", "type": "address" }, { - "internalType": "string", - "name": "methodSignature", - "type": "string" + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "name": "Unauthorized", - "type": "error" + "name": "AdminChanged", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" } ], - "name": "Initialized", + "name": "BeaconUpgraded", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "oldAccessControlManager", + "name": "implementation", "type": "address" - }, + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_Tron": { + "address": "0x712774CBFFCBD60e9825871CcEFF2F917442b2c3", + "abi": [ + { + "inputs": [ { - "indexed": false, "internalType": "address", - "name": "newAccessControlManager", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "NewAccessControlManager", - "type": "event" + "stateMutability": "payable", + "type": "constructor" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "previousOwner", + "name": "previousAdmin", "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newOwner", + "name": "newAdmin", "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "AdminChanged", "type": "event" }, { @@ -51430,17 +52539,11 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", + "name": "beacon", "type": "address" } ], - "name": "OwnershipTransferred", + "name": "BeaconUpgraded", "type": "event" }, { @@ -51449,405 +52552,355 @@ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "implementation", "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "upperBound", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "lowerBound", - "type": "uint256" } ], - "name": "ValidateConfigAdded", + "name": "Upgraded", "type": "event" }, { - "inputs": [], - "name": "BNB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vWBNB_LiquidStakedBNB": { + "address": "0x231dED0Dfc99634e52EE1a1329586bc970d773b3", + "abi": [ { - "inputs": [], - "name": "accessControlManager", - "outputs": [ + "inputs": [ { - "internalType": "contract IAccessControlManagerV8", - "name": "", + "internalType": "address", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "accessControlManager_", + "name": "previousAdmin", "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ + }, { + "indexed": false, "internalType": "address", - "name": "", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "beacon", "type": "address" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "accessControlManager_", + "name": "implementation", "type": "address" } ], - "name": "setAccessControlManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "upperBoundRatio", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lowerBoundRatio", - "type": "uint256" - } - ], - "internalType": "struct BoundValidator.ValidateConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "setValidateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vWIN_Tron": { + "address": "0xEe543D5de2Dbb5b07675Fc72831A2f1812428393", + "abi": [ { "inputs": [ { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "upperBoundRatio", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lowerBoundRatio", - "type": "uint256" - } - ], - "internalType": "struct BoundValidator.ValidateConfig[]", - "name": "configs", - "type": "tuple[]" + "internalType": "address", + "name": "beacon", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "setValidateConfigs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "newOwner", + "name": "previousAdmin", "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "vBnb", - "outputs": [ + }, { + "indexed": false, "internalType": "address", - "name": "", + "name": "newAdmin", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { - "inputs": [], - "name": "vai", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "beacon", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "name": "validateConfigs", - "outputs": [ + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vagEUR_Stablecoins": { + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", + "abi": [ + { + "inputs": [ { "internalType": "address", - "name": "asset", + "name": "beacon", "type": "address" }, { - "internalType": "uint256", - "name": "upperBoundRatio", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lowerBoundRatio", - "type": "uint256" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "vToken", + "name": "previousAdmin", "type": "address" }, { - "internalType": "uint256", - "name": "reportedPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "anchorPrice", - "type": "uint256" - } - ], - "name": "validatePriceWithAnchorPrice", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "_logic", + "name": "beacon", "type": "address" - }, + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "admin_", + "name": "implementation", "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" } ], + "name": "Upgraded", + "type": "event" + }, + { "stateMutability": "payable", - "type": "constructor" + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" } ] }, - "BoundValidator_Implementation": { - "address": "0x4915F67a57FDcbA22535F0F021D64b66b095d026", + "VToken_vankrBNB_DeFi": { + "address": "0xe507B30C41E9e375BCe05197c1e09fc9ee40c0f6", "abi": [ { "inputs": [ { "internalType": "address", - "name": "vBnbAddress", + "name": "beacon", "type": "address" }, { - "internalType": "address", - "name": "vaiAddress", - "type": "address" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "sender", + "name": "previousAdmin", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "calledContract", + "name": "newAdmin", "type": "address" - }, - { - "internalType": "string", - "name": "methodSignature", - "type": "string" } ], - "name": "Unauthorized", - "type": "error" + "name": "AdminChanged", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" } ], - "name": "Initialized", + "name": "BeaconUpgraded", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "oldAccessControlManager", - "type": "address" - }, - { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "newAccessControlManager", + "name": "implementation", "type": "address" } ], - "name": "NewAccessControlManager", + "name": "Upgraded", "type": "event" }, { - "anonymous": false, + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vankrBNB_LiquidStakedBNB": { + "address": "0x57a664Dd7f1dE19545fEE9c86C949e3BF43d6D47", + "abi": [ + { "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "beacon", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "stateMutability": "payable", + "type": "constructor" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "previousOwner", + "name": "previousAdmin", "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newOwner", + "name": "newAdmin", "type": "address" } ], - "name": "OwnershipTransferred", + "name": "AdminChanged", "type": "event" }, { @@ -51856,414 +52909,112 @@ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "beacon", "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "upperBound", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "lowerBound", - "type": "uint256" } ], - "name": "ValidateConfigAdded", + "name": "BeaconUpgraded", "type": "event" }, { - "inputs": [], - "name": "BNB_ADDR", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "fallback" }, { - "inputs": [], - "name": "accessControlManager", - "outputs": [ + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vstkBNB_LiquidStakedBNB": { + "address": "0x75aa42c832a8911B77219DbeBABBB40040d16987", + "abi": [ + { + "inputs": [ { - "internalType": "contract IAccessControlManagerV8", - "name": "", + "internalType": "address", + "name": "beacon", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "view", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "accessControlManager_", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { - "inputs": [], - "name": "owner", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "beacon", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "implementation", "type": "address" } ], - "stateMutability": "view", - "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": [ - { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "upperBoundRatio", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lowerBoundRatio", - "type": "uint256" - } - ], - "internalType": "struct BoundValidator.ValidateConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "setValidateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "upperBoundRatio", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lowerBoundRatio", - "type": "uint256" - } - ], - "internalType": "struct BoundValidator.ValidateConfig[]", - "name": "configs", - "type": "tuple[]" - } - ], - "name": "setValidateConfigs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "vBnb", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "vai", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "validateConfigs", - "outputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "upperBoundRatio", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lowerBoundRatio", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "reportedPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "anchorPrice", - "type": "uint256" - } - ], - "name": "validatePriceWithAnchorPrice", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ] - }, - "BoundValidator_Proxy": { - "address": "0x2842140e4Ad3a92e9af30e27e290300dd785076d", - "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" + "name": "Upgraded", + "type": "event" }, { "stateMutability": "payable", "type": "fallback" }, - { - "inputs": [], - "name": "admin", - "outputs": [ - { - "internalType": "address", - "name": "admin_", - "type": "address" - } - ], - "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" } ] }, - "ChainlinkOracle": { - "address": "0xCeA29f1266e880A1482c06eD656cD08C148BaA32", + "BinanceOracle": { + "address": "0xB58BFDCE610042311Dc0e034a80Cc7776c1D68f5", "abi": [ { "anonymous": false, @@ -52413,38 +53164,38 @@ "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "oldAccessControlManager", - "type": "address" + "indexed": true, + "internalType": "string", + "name": "asset", + "type": "string" }, { "indexed": false, - "internalType": "address", - "name": "newAccessControlManager", - "type": "address" + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" } ], - "name": "NewAccessControlManager", + "name": "MaxStalePeriodAdded", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "previousOwner", + "name": "oldAccessControlManager", "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newOwner", + "name": "newAccessControlManager", "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "NewAccessControlManager", "type": "event" }, { @@ -52463,7 +53214,7 @@ "type": "address" } ], - "name": "OwnershipTransferred", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -52472,56 +53223,32 @@ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "previousOwner", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousPriceMantissa", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newPriceMantissa", - "type": "uint256" - } - ], - "name": "PricePosted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ { "indexed": true, "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "feed", + "name": "newOwner", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" } ], - "name": "TokenConfigAdded", + "name": "OwnershipTransferred", "type": "event" }, { "inputs": [], - "name": "BNB_ADDR", + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -52531,17 +53258,10 @@ }, { "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "accessControlManager", + "name": "getFeedRegistryAddress", "outputs": [ { - "internalType": "contract IAccessControlManagerV8", + "internalType": "address", "name": "", "type": "address" } @@ -52572,7 +53292,12 @@ "inputs": [ { "internalType": "address", - "name": "accessControlManager_", + "name": "_sidRegistryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_accessControlManager", "type": "address" } ], @@ -52582,13 +53307,19 @@ "type": "function" }, { - "inputs": [], - "name": "owner", + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "maxStalePeriod", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", @@ -52596,7 +53327,7 @@ }, { "inputs": [], - "name": "pendingOwner", + "name": "owner", "outputs": [ { "internalType": "address", @@ -52608,21 +53339,15 @@ "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "pendingOwner", + "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "name": "prices", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], "stateMutability": "view", "type": "function" }, @@ -52649,152 +53374,58 @@ { "inputs": [ { - "internalType": "address", - "name": "asset", - "type": "address" + "internalType": "string", + "name": "symbol", + "type": "string" }, { "internalType": "uint256", - "name": "price", + "name": "_maxStalePeriod", "type": "uint256" } ], - "name": "setDirectPrice", + "name": "setMaxStalePeriod", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "sidRegistryAddress", + "outputs": [ { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "feed", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" - } - ], - "internalType": "struct ChainlinkOracle.TokenConfig", - "name": "tokenConfig", - "type": "tuple" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "setTokenConfig", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "feed", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" - } - ], - "internalType": "struct ChainlinkOracle.TokenConfig[]", - "name": "tokenConfigs_", - "type": "tuple[]" + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "setTokenConfigs", + "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "vBnb", + "outputs": [ { - "internalType": "contract VBep20Interface", - "name": "vToken", + "internalType": "address", + "name": "", "type": "address" - }, - { - "internalType": "uint256", - "name": "underlyingPriceMantissa", - "type": "uint256" } ], - "name": "setUnderlyingPrice", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "tokenConfigs", - "outputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "feed", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "vBnb", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", + "stateMutability": "view", "type": "function" }, { @@ -52833,8 +53464,8 @@ } ] }, - "ChainlinkOracle_Implementation": { - "address": "0xa074529FD3d0E7261A730d0f867107BA0C20d74A", + "BinanceOracle_Implementation": { + "address": "0xCd64844CD0E8E34782cd0d1bF3E537bf7b474FAe", "abi": [ { "inputs": [ @@ -52890,38 +53521,38 @@ "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "oldAccessControlManager", - "type": "address" + "indexed": true, + "internalType": "string", + "name": "asset", + "type": "string" }, { "indexed": false, - "internalType": "address", - "name": "newAccessControlManager", - "type": "address" + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" } ], - "name": "NewAccessControlManager", + "name": "MaxStalePeriodAdded", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "previousOwner", + "name": "oldAccessControlManager", "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newOwner", + "name": "newAccessControlManager", "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "NewAccessControlManager", "type": "event" }, { @@ -52940,7 +53571,7 @@ "type": "address" } ], - "name": "OwnershipTransferred", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -52949,56 +53580,32 @@ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "previousOwner", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousPriceMantissa", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newPriceMantissa", - "type": "uint256" - } - ], - "name": "PricePosted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ { "indexed": true, "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "feed", + "name": "newOwner", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" } ], - "name": "TokenConfigAdded", + "name": "OwnershipTransferred", "type": "event" }, { "inputs": [], - "name": "BNB_ADDR", + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -53008,17 +53615,10 @@ }, { "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "accessControlManager", + "name": "getFeedRegistryAddress", "outputs": [ { - "internalType": "contract IAccessControlManagerV8", + "internalType": "address", "name": "", "type": "address" } @@ -53049,7 +53649,12 @@ "inputs": [ { "internalType": "address", - "name": "accessControlManager_", + "name": "_sidRegistryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_accessControlManager", "type": "address" } ], @@ -53059,13 +53664,19 @@ "type": "function" }, { - "inputs": [], - "name": "owner", + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "maxStalePeriod", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", @@ -53073,7 +53684,7 @@ }, { "inputs": [], - "name": "pendingOwner", + "name": "owner", "outputs": [ { "internalType": "address", @@ -53085,21 +53696,15 @@ "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "pendingOwner", + "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "name": "prices", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], "stateMutability": "view", "type": "function" }, @@ -53126,123 +53731,29 @@ { "inputs": [ { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "price", - "type": "uint256" - } - ], - "name": "setDirectPrice", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "feed", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" - } - ], - "internalType": "struct ChainlinkOracle.TokenConfig", - "name": "tokenConfig", - "type": "tuple" - } - ], - "name": "setTokenConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "feed", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" - } - ], - "internalType": "struct ChainlinkOracle.TokenConfig[]", - "name": "tokenConfigs_", - "type": "tuple[]" - } - ], - "name": "setTokenConfigs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract VBep20Interface", - "name": "vToken", - "type": "address" + "internalType": "string", + "name": "symbol", + "type": "string" }, { "internalType": "uint256", - "name": "underlyingPriceMantissa", + "name": "_maxStalePeriod", "type": "uint256" } ], - "name": "setUnderlyingPrice", + "name": "setMaxStalePeriod", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "tokenConfigs", + "inputs": [], + "name": "sidRegistryAddress", "outputs": [ { "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "feed", + "name": "", "type": "address" - }, - { - "internalType": "uint256", - "name": "maxStalePeriod", - "type": "uint256" } ], "stateMutability": "view", @@ -53289,8 +53800,8 @@ } ] }, - "ChainlinkOracle_Proxy": { - "address": "0xCeA29f1266e880A1482c06eD656cD08C148BaA32", + "BinanceOracle_Proxy": { + "address": "0xB58BFDCE610042311Dc0e034a80Cc7776c1D68f5", "abi": [ { "inputs": [ @@ -53425,173 +53936,8 @@ } ] }, - "DefaultProxyAdmin": { - "address": "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", - "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" - } - ] - }, - "PythOracle": { - "address": "0x94E1534c14e0736BB24decA625f2F5364B198E0C", + "BoundValidator": { + "address": "0x2842140e4Ad3a92e9af30e27e290300dd785076d", "abi": [ { "anonymous": false, @@ -53800,42 +54146,23 @@ { "indexed": true, "internalType": "address", - "name": "oldPythOracle", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newPythOracle", - "type": "address" - } - ], - "name": "PythOracleSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "vToken", + "name": "asset", "type": "address" }, { "indexed": true, - "internalType": "bytes32", - "name": "pythId", - "type": "bytes32" + "internalType": "uint256", + "name": "upperBound", + "type": "uint256" }, { "indexed": true, - "internalType": "uint64", - "name": "maxStalePeriod", - "type": "uint64" + "internalType": "uint256", + "name": "lowerBound", + "type": "uint256" } ], - "name": "TokenConfigAdded", + "name": "ValidateConfigAdded", "type": "event" }, { @@ -53851,19 +54178,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "EXP_SCALE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "acceptOwnership", @@ -53888,31 +54202,7 @@ "inputs": [ { "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "getUnderlyingPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "underlyingPythOracle_", - "type": "address" - }, - { - "internalType": "address", - "name": "accessControlManager_", + "name": "accessControlManager_", "type": "address" } ], @@ -53971,28 +54261,28 @@ "inputs": [ { "components": [ - { - "internalType": "bytes32", - "name": "pythId", - "type": "bytes32" - }, { "internalType": "address", "name": "asset", "type": "address" }, { - "internalType": "uint64", - "name": "maxStalePeriod", - "type": "uint64" + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" } ], - "internalType": "struct PythOracle.TokenConfig", - "name": "tokenConfig", + "internalType": "struct BoundValidator.ValidateConfig", + "name": "config", "type": "tuple" } ], - "name": "setTokenConfig", + "name": "setValidateConfig", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -54001,28 +54291,28 @@ "inputs": [ { "components": [ - { - "internalType": "bytes32", - "name": "pythId", - "type": "bytes32" - }, { "internalType": "address", "name": "asset", "type": "address" }, { - "internalType": "uint64", - "name": "maxStalePeriod", - "type": "uint64" + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" } ], - "internalType": "struct PythOracle.TokenConfig[]", - "name": "tokenConfigs_", + "internalType": "struct BoundValidator.ValidateConfig[]", + "name": "configs", "type": "tuple[]" } ], - "name": "setTokenConfigs", + "name": "setValidateConfigs", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -54030,40 +54320,37 @@ { "inputs": [ { - "internalType": "contract IPyth", - "name": "underlyingPythOracle_", + "internalType": "address", + "name": "newOwner", "type": "address" } ], - "name": "setUnderlyingPythOracle", + "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "vBnb", + "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "name": "tokenConfigs", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vai", "outputs": [ - { - "internalType": "bytes32", - "name": "pythId", - "type": "bytes32" - }, { "internalType": "address", - "name": "asset", + "name": "", "type": "address" - }, - { - "internalType": "uint64", - "name": "maxStalePeriod", - "type": "uint64" } ], "stateMutability": "view", @@ -54073,49 +54360,55 @@ "inputs": [ { "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "underlyingPythOracle", + "name": "validateConfigs", "outputs": [ { - "internalType": "contract IPyth", - "name": "", + "internalType": "address", + "name": "asset", "type": "address" + }, + { + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "vBnb", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "vToken", "type": "address" + }, + { + "internalType": "uint256", + "name": "reportedPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "anchorPrice", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "vai", + "name": "validatePriceWithAnchorPrice", "outputs": [ { - "internalType": "address", + "internalType": "bool", "name": "", - "type": "address" + "type": "bool" } ], "stateMutability": "view", @@ -54144,8 +54437,8 @@ } ] }, - "PythOracle_Implementation": { - "address": "0xb8a450101DF8ab770c8F8521E189a4B39e7Cf5f5", + "BoundValidator_Implementation": { + "address": "0x4915F67a57FDcbA22535F0F021D64b66b095d026", "abi": [ { "inputs": [ @@ -54260,42 +54553,23 @@ { "indexed": true, "internalType": "address", - "name": "oldPythOracle", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newPythOracle", - "type": "address" - } - ], - "name": "PythOracleSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "vToken", + "name": "asset", "type": "address" }, { "indexed": true, - "internalType": "bytes32", - "name": "pythId", - "type": "bytes32" + "internalType": "uint256", + "name": "upperBound", + "type": "uint256" }, { "indexed": true, - "internalType": "uint64", - "name": "maxStalePeriod", - "type": "uint64" + "internalType": "uint256", + "name": "lowerBound", + "type": "uint256" } ], - "name": "TokenConfigAdded", + "name": "ValidateConfigAdded", "type": "event" }, { @@ -54311,19 +54585,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "EXP_SCALE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "acceptOwnership", @@ -54346,30 +54607,6 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "getUnderlyingPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "underlyingPythOracle_", - "type": "address" - }, { "internalType": "address", "name": "accessControlManager_", @@ -54431,28 +54668,28 @@ "inputs": [ { "components": [ - { - "internalType": "bytes32", - "name": "pythId", - "type": "bytes32" - }, { "internalType": "address", "name": "asset", "type": "address" }, { - "internalType": "uint64", - "name": "maxStalePeriod", - "type": "uint64" + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" } ], - "internalType": "struct PythOracle.TokenConfig", - "name": "tokenConfig", + "internalType": "struct BoundValidator.ValidateConfig", + "name": "config", "type": "tuple" } ], - "name": "setTokenConfig", + "name": "setValidateConfig", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -54461,28 +54698,28 @@ "inputs": [ { "components": [ - { - "internalType": "bytes32", - "name": "pythId", - "type": "bytes32" - }, { "internalType": "address", "name": "asset", "type": "address" }, { - "internalType": "uint64", - "name": "maxStalePeriod", - "type": "uint64" + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" } ], - "internalType": "struct PythOracle.TokenConfig[]", - "name": "tokenConfigs_", + "internalType": "struct BoundValidator.ValidateConfig[]", + "name": "configs", "type": "tuple[]" } ], - "name": "setTokenConfigs", + "name": "setValidateConfigs", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -54490,40 +54727,37 @@ { "inputs": [ { - "internalType": "contract IPyth", - "name": "underlyingPythOracle_", + "internalType": "address", + "name": "newOwner", "type": "address" } ], - "name": "setUnderlyingPythOracle", + "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "vBnb", + "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "name": "tokenConfigs", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vai", "outputs": [ - { - "internalType": "bytes32", - "name": "pythId", - "type": "bytes32" - }, { "internalType": "address", - "name": "asset", + "name": "", "type": "address" - }, - { - "internalType": "uint64", - "name": "maxStalePeriod", - "type": "uint64" } ], "stateMutability": "view", @@ -54533,49 +54767,55 @@ "inputs": [ { "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "underlyingPythOracle", + "name": "validateConfigs", "outputs": [ { - "internalType": "contract IPyth", - "name": "", + "internalType": "address", + "name": "asset", "type": "address" + }, + { + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "vBnb", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "vToken", "type": "address" + }, + { + "internalType": "uint256", + "name": "reportedPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "anchorPrice", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "vai", + "name": "validatePriceWithAnchorPrice", "outputs": [ { - "internalType": "address", + "internalType": "bool", "name": "", - "type": "address" + "type": "bool" } ], "stateMutability": "view", @@ -54583,8 +54823,8 @@ } ] }, - "PythOracle_Proxy": { - "address": "0x94E1534c14e0736BB24decA625f2F5364B198E0C", + "BoundValidator_Proxy": { + "address": "0x2842140e4Ad3a92e9af30e27e290300dd785076d", "abi": [ { "inputs": [ @@ -54719,8 +54959,8 @@ } ] }, - "ResilientOracle": { - "address": "0x3cD69251D04A28d887Ac14cbe2E14c52F3D57823", + "ChainlinkOracle": { + "address": "0xCeA29f1266e880A1482c06eD656cD08C148BaA32", "abi": [ { "anonymous": false, @@ -54891,48 +55131,17 @@ { "indexed": true, "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "role", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "enable", - "type": "bool" - } - ], - "name": "OracleEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "asset", + "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "oracle", + "name": "newOwner", "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "role", - "type": "uint256" } ], - "name": "OracleSet", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -54951,7 +55160,7 @@ "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "OwnershipTransferred", "type": "event" }, { @@ -54960,30 +55169,23 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "asset", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "indexed": false, + "internalType": "uint256", + "name": "previousPriceMantissa", + "type": "uint256" + }, { "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "newPriceMantissa", + "type": "uint256" } ], - "name": "Paused", + "name": "PricePosted", "type": "event" }, { @@ -54996,40 +55198,21 @@ "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "mainOracle", - "type": "address" - }, - { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "pivotOracle", + "name": "feed", "type": "address" }, { "indexed": false, - "internalType": "address", - "name": "fallbackOracle", - "type": "address" + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" } ], "name": "TokenConfigAdded", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, { "inputs": [], "name": "BNB_ADDR", @@ -55043,19 +55226,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "INVALID_PRICE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "acceptOwnership", @@ -55076,107 +55246,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "boundValidator", - "outputs": [ - { - "internalType": "contract BoundValidatorInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "enum ResilientOracle.OracleRole", - "name": "role", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "enable", - "type": "bool" - } - ], - "name": "enableOracle", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "enum ResilientOracle.OracleRole", - "name": "role", - "type": "uint8" - } - ], - "name": "getOracle", - "outputs": [ - { - "internalType": "address", - "name": "oracle", - "type": "address" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "getTokenConfig", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address[3]", - "name": "oracles", - "type": "address[3]" - }, - { - "internalType": "bool[3]", - "name": "enableFlagsForOracles", - "type": "bool[3]" - } - ], - "internalType": "struct ResilientOracle.TokenConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -55224,34 +55293,33 @@ }, { "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", + "name": "pendingOwner", "outputs": [ { - "internalType": "bool", + "internalType": "address", "name": "", - "type": "bool" + "type": "address" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], + "name": "prices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "view", "type": "function" }, @@ -55283,17 +55351,12 @@ "type": "address" }, { - "internalType": "address", - "name": "oracle", - "type": "address" - }, - { - "internalType": "enum ResilientOracle.OracleRole", - "name": "role", - "type": "uint8" + "internalType": "uint256", + "name": "price", + "type": "uint256" } ], - "name": "setOracle", + "name": "setDirectPrice", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -55308,17 +55371,17 @@ "type": "address" }, { - "internalType": "address[3]", - "name": "oracles", - "type": "address[3]" + "internalType": "address", + "name": "feed", + "type": "address" }, { - "internalType": "bool[3]", - "name": "enableFlagsForOracles", - "type": "bool[3]" + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" } ], - "internalType": "struct ResilientOracle.TokenConfig", + "internalType": "struct ChainlinkOracle.TokenConfig", "name": "tokenConfig", "type": "tuple" } @@ -55338,17 +55401,17 @@ "type": "address" }, { - "internalType": "address[3]", - "name": "oracles", - "type": "address[3]" + "internalType": "address", + "name": "feed", + "type": "address" }, { - "internalType": "bool[3]", - "name": "enableFlagsForOracles", - "type": "bool[3]" + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" } ], - "internalType": "struct ResilientOracle.TokenConfig[]", + "internalType": "struct ChainlinkOracle.TokenConfig[]", "name": "tokenConfigs_", "type": "tuple[]" } @@ -55361,32 +55424,59 @@ { "inputs": [ { - "internalType": "address", - "name": "newOwner", + "internalType": "contract VBep20Interface", + "name": "vToken", "type": "address" + }, + { + "internalType": "uint256", + "name": "underlyingPriceMantissa", + "type": "uint256" } ], - "name": "transferOwnership", + "name": "setUnderlyingPrice", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vToken", + "name": "newOwner", "type": "address" } ], - "name": "updatePrice", + "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -55440,8 +55530,8 @@ } ] }, - "ResilientOracle_Implementation": { - "address": "0xF53cFE89b4c3eFCbdd9aF712e94017454d43c181", + "ChainlinkOracle_Implementation": { + "address": "0xa074529FD3d0E7261A730d0f867107BA0C20d74A", "abi": [ { "inputs": [ @@ -55454,11 +55544,6 @@ "internalType": "address", "name": "vaiAddress", "type": "address" - }, - { - "internalType": "contract BoundValidatorInterface", - "name": "_boundValidator", - "type": "address" } ], "stateMutability": "nonpayable", @@ -55523,48 +55608,17 @@ { "indexed": true, "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "role", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "enable", - "type": "bool" - } - ], - "name": "OracleEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "asset", + "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "oracle", + "name": "newOwner", "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "role", - "type": "uint256" } ], - "name": "OracleSet", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -55583,7 +55637,7 @@ "type": "address" } ], - "name": "OwnershipTransferStarted", + "name": "OwnershipTransferred", "type": "event" }, { @@ -55592,30 +55646,23 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "asset", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "indexed": false, + "internalType": "uint256", + "name": "previousPriceMantissa", + "type": "uint256" + }, { "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" + "internalType": "uint256", + "name": "newPriceMantissa", + "type": "uint256" } ], - "name": "Paused", + "name": "PricePosted", "type": "event" }, { @@ -55628,46 +55675,47 @@ "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "mainOracle", - "type": "address" - }, - { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "pivotOracle", + "name": "feed", "type": "address" }, { "indexed": false, - "internalType": "address", - "name": "fallbackOracle", - "type": "address" + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" } ], "name": "TokenConfigAdded", "type": "event" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "BNB_ADDR", + "outputs": [ { - "indexed": false, "internalType": "address", - "name": "account", + "name": "", "type": "address" } ], - "name": "Unpaused", - "type": "event" + "stateMutability": "view", + "type": "function" }, { "inputs": [], - "name": "BNB_ADDR", + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -55676,8 +55724,14 @@ "type": "function" }, { - "inputs": [], - "name": "INVALID_PRICE", + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", "outputs": [ { "internalType": "uint256", @@ -55689,18 +55743,24 @@ "type": "function" }, { - "inputs": [], - "name": "acceptOwnership", + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "accessControlManager", + "name": "owner", "outputs": [ { - "internalType": "contract IAccessControlManagerV8", + "internalType": "address", "name": "", "type": "address" } @@ -55710,10 +55770,10 @@ }, { "inputs": [], - "name": "boundValidator", + "name": "pendingOwner", "outputs": [ { - "internalType": "contract BoundValidatorInterface", + "internalType": "address", "name": "", "type": "address" } @@ -55725,21 +55785,24 @@ "inputs": [ { "internalType": "address", - "name": "asset", + "name": "", "type": "address" - }, - { - "internalType": "enum ResilientOracle.OracleRole", - "name": "role", - "type": "uint8" - }, + } + ], + "name": "prices", + "outputs": [ { - "internalType": "bool", - "name": "enable", - "type": "bool" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "enableOracle", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -55748,184 +55811,29 @@ "inputs": [ { "internalType": "address", - "name": "vToken", + "name": "accessControlManager_", "type": "address" - }, - { - "internalType": "enum ResilientOracle.OracleRole", - "name": "role", - "type": "uint8" } ], - "name": "getOracle", - "outputs": [ + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "oracle", + "name": "asset", "type": "address" }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "getTokenConfig", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address[3]", - "name": "oracles", - "type": "address[3]" - }, - { - "internalType": "bool[3]", - "name": "enableFlagsForOracles", - "type": "bool[3]" - } - ], - "internalType": "struct ResilientOracle.TokenConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "getUnderlyingPrice", - "outputs": [ { "internalType": "uint256", - "name": "", + "name": "price", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "accessControlManager_", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "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": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "oracle", - "type": "address" - }, - { - "internalType": "enum ResilientOracle.OracleRole", - "name": "role", - "type": "uint8" - } - ], - "name": "setOracle", + "name": "setDirectPrice", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -55940,17 +55848,17 @@ "type": "address" }, { - "internalType": "address[3]", - "name": "oracles", - "type": "address[3]" + "internalType": "address", + "name": "feed", + "type": "address" }, { - "internalType": "bool[3]", - "name": "enableFlagsForOracles", - "type": "bool[3]" + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" } ], - "internalType": "struct ResilientOracle.TokenConfig", + "internalType": "struct ChainlinkOracle.TokenConfig", "name": "tokenConfig", "type": "tuple" } @@ -55970,17 +55878,17 @@ "type": "address" }, { - "internalType": "address[3]", - "name": "oracles", - "type": "address[3]" + "internalType": "address", + "name": "feed", + "type": "address" }, { - "internalType": "bool[3]", - "name": "enableFlagsForOracles", - "type": "bool[3]" + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" } ], - "internalType": "struct ResilientOracle.TokenConfig[]", + "internalType": "struct ChainlinkOracle.TokenConfig[]", "name": "tokenConfigs_", "type": "tuple[]" } @@ -55993,32 +55901,59 @@ { "inputs": [ { - "internalType": "address", - "name": "newOwner", + "internalType": "contract VBep20Interface", + "name": "vToken", "type": "address" + }, + { + "internalType": "uint256", + "name": "underlyingPriceMantissa", + "type": "uint256" } ], - "name": "transferOwnership", + "name": "setUnderlyingPrice", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "vToken", + "name": "newOwner", "type": "address" } ], - "name": "updatePrice", + "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -56051,8 +55986,8 @@ } ] }, - "ResilientOracle_Proxy": { - "address": "0x3cD69251D04A28d887Ac14cbe2E14c52F3D57823", + "ChainlinkOracle_Proxy": { + "address": "0xCeA29f1266e880A1482c06eD656cD08C148BaA32", "abi": [ { "inputs": [ @@ -56187,8 +56122,8 @@ } ] }, - "TwapOracle": { - "address": "0x3eeE05d929D1E9816185B1b6d8c470eC192b4432", + "PythOracle": { + "address": "0x94E1534c14e0736BB24decA625f2F5364B198E0C", "abi": [ { "anonymous": false, @@ -56321,37 +56256,6 @@ "name": "Unauthorized", "type": "error" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "price", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldTimestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newTimestamp", - "type": "uint256" - } - ], - "name": "AnchorPriceUpdated", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -56428,23 +56332,17 @@ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "oldPythOracle", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "pancakePool", + "name": "newPythOracle", "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" } ], - "name": "TokenConfigAdded", + "name": "PythOracleSet", "type": "event" }, { @@ -56453,45 +56351,33 @@ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "vToken", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "oldTimestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldAcc", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newTimestamp", - "type": "uint256" + "indexed": true, + "internalType": "bytes32", + "name": "pythId", + "type": "bytes32" }, { - "indexed": false, - "internalType": "uint256", - "name": "newAcc", - "type": "uint256" + "indexed": true, + "internalType": "uint64", + "name": "maxStalePeriod", + "type": "uint64" } ], - "name": "TwapWindowUpdated", + "name": "TokenConfigAdded", "type": "event" }, { "inputs": [], - "name": "BNB_BASE_UNIT", + "name": "BNB_ADDR", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -56499,7 +56385,7 @@ }, { "inputs": [], - "name": "BUSD_BASE_UNIT", + "name": "EXP_SCALE", "outputs": [ { "internalType": "uint256", @@ -56510,19 +56396,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "WBNB", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "acceptOwnership", @@ -56543,57 +56416,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "baseUnit", - "type": "uint256" - }, - { - "internalType": "address", - "name": "pancakePool", - "type": "address" - }, - { - "internalType": "bool", - "name": "isBnbBased", - "type": "bool" - }, - { - "internalType": "bool", - "name": "isReversedPool", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" - } - ], - "internalType": "struct TwapOracle.TokenConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "currentCumulativePrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -56615,6 +56437,11 @@ }, { "inputs": [ + { + "internalType": "address", + "name": "underlyingPythOracle_", + "type": "address" + }, { "internalType": "address", "name": "accessControlManager_", @@ -56626,35 +56453,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "observations", - "outputs": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "acc", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "owner", @@ -56681,25 +56479,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "prices", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "renounceOwnership", @@ -56725,38 +56504,23 @@ { "components": [ { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "baseUnit", - "type": "uint256" + "internalType": "bytes32", + "name": "pythId", + "type": "bytes32" }, { "internalType": "address", - "name": "pancakePool", + "name": "asset", "type": "address" }, { - "internalType": "bool", - "name": "isBnbBased", - "type": "bool" - }, - { - "internalType": "bool", - "name": "isReversedPool", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" + "internalType": "uint64", + "name": "maxStalePeriod", + "type": "uint64" } ], - "internalType": "struct TwapOracle.TokenConfig", - "name": "config", + "internalType": "struct PythOracle.TokenConfig", + "name": "tokenConfig", "type": "tuple" } ], @@ -56770,38 +56534,23 @@ { "components": [ { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "baseUnit", - "type": "uint256" + "internalType": "bytes32", + "name": "pythId", + "type": "bytes32" }, { "internalType": "address", - "name": "pancakePool", + "name": "asset", "type": "address" }, { - "internalType": "bool", - "name": "isBnbBased", - "type": "bool" - }, - { - "internalType": "bool", - "name": "isReversedPool", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" + "internalType": "uint64", + "name": "maxStalePeriod", + "type": "uint64" } ], - "internalType": "struct TwapOracle.TokenConfig[]", - "name": "configs", + "internalType": "struct PythOracle.TokenConfig[]", + "name": "tokenConfigs_", "type": "tuple[]" } ], @@ -56813,42 +56562,40 @@ { "inputs": [ { - "internalType": "address", - "name": "", + "internalType": "contract IPyth", + "name": "underlyingPythOracle_", "type": "address" } ], - "name": "tokenConfigs", - "outputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "baseUnit", - "type": "uint256" - }, + "name": "setUnderlyingPythOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "pancakePool", + "name": "", "type": "address" - }, + } + ], + "name": "tokenConfigs", + "outputs": [ { - "internalType": "bool", - "name": "isBnbBased", - "type": "bool" + "internalType": "bytes32", + "name": "pythId", + "type": "bytes32" }, { - "internalType": "bool", - "name": "isReversedPool", - "type": "bool" + "internalType": "address", + "name": "asset", + "type": "address" }, { - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" + "internalType": "uint64", + "name": "maxStalePeriod", + "type": "uint64" } ], "stateMutability": "view", @@ -56868,22 +56615,16 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "updateTwap", + "inputs": [], + "name": "underlyingPythOracle", "outputs": [ { - "internalType": "uint256", + "internalType": "contract IPyth", "name": "", - "type": "uint256" + "type": "address" } ], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -56912,25 +56653,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "windowStart", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -56954,8 +56676,8 @@ } ] }, - "TwapOracle_Implementation": { - "address": "0x572ec272B4Ae3a50B99905AFd78671F84474ffd1", + "PythOracle_Implementation": { + "address": "0xb8a450101DF8ab770c8F8521E189a4B39e7Cf5f5", "abi": [ { "inputs": [ @@ -56964,11 +56686,6 @@ "name": "vBnbAddress", "type": "address" }, - { - "internalType": "address", - "name": "wBnbAddress", - "type": "address" - }, { "internalType": "address", "name": "vaiAddress", @@ -56999,37 +56716,6 @@ "name": "Unauthorized", "type": "error" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "price", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldTimestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newTimestamp", - "type": "uint256" - } - ], - "name": "AnchorPriceUpdated", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -57106,23 +56792,17 @@ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "oldPythOracle", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "pancakePool", + "name": "newPythOracle", "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" } ], - "name": "TokenConfigAdded", + "name": "PythOracleSet", "type": "event" }, { @@ -57131,45 +56811,33 @@ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "vToken", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "oldTimestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldAcc", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newTimestamp", - "type": "uint256" + "indexed": true, + "internalType": "bytes32", + "name": "pythId", + "type": "bytes32" }, { - "indexed": false, - "internalType": "uint256", - "name": "newAcc", - "type": "uint256" + "indexed": true, + "internalType": "uint64", + "name": "maxStalePeriod", + "type": "uint64" } ], - "name": "TwapWindowUpdated", + "name": "TokenConfigAdded", "type": "event" }, { "inputs": [], - "name": "BNB_BASE_UNIT", + "name": "BNB_ADDR", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -57177,7 +56845,7 @@ }, { "inputs": [], - "name": "BUSD_BASE_UNIT", + "name": "EXP_SCALE", "outputs": [ { "internalType": "uint256", @@ -57188,19 +56856,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "WBNB", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "acceptOwnership", @@ -57221,57 +56876,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "baseUnit", - "type": "uint256" - }, - { - "internalType": "address", - "name": "pancakePool", - "type": "address" - }, - { - "internalType": "bool", - "name": "isBnbBased", - "type": "bool" - }, - { - "internalType": "bool", - "name": "isReversedPool", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" - } - ], - "internalType": "struct TwapOracle.TokenConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "currentCumulativePrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -57293,6 +56897,11 @@ }, { "inputs": [ + { + "internalType": "address", + "name": "underlyingPythOracle_", + "type": "address" + }, { "internalType": "address", "name": "accessControlManager_", @@ -57304,35 +56913,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "observations", - "outputs": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "acc", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "owner", @@ -57359,25 +56939,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "prices", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "renounceOwnership", @@ -57403,38 +56964,23 @@ { "components": [ { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "baseUnit", - "type": "uint256" + "internalType": "bytes32", + "name": "pythId", + "type": "bytes32" }, { "internalType": "address", - "name": "pancakePool", + "name": "asset", "type": "address" }, { - "internalType": "bool", - "name": "isBnbBased", - "type": "bool" - }, - { - "internalType": "bool", - "name": "isReversedPool", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" + "internalType": "uint64", + "name": "maxStalePeriod", + "type": "uint64" } ], - "internalType": "struct TwapOracle.TokenConfig", - "name": "config", + "internalType": "struct PythOracle.TokenConfig", + "name": "tokenConfig", "type": "tuple" } ], @@ -57448,38 +56994,23 @@ { "components": [ { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "baseUnit", - "type": "uint256" + "internalType": "bytes32", + "name": "pythId", + "type": "bytes32" }, { "internalType": "address", - "name": "pancakePool", + "name": "asset", "type": "address" }, { - "internalType": "bool", - "name": "isBnbBased", - "type": "bool" - }, - { - "internalType": "bool", - "name": "isReversedPool", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" + "internalType": "uint64", + "name": "maxStalePeriod", + "type": "uint64" } ], - "internalType": "struct TwapOracle.TokenConfig[]", - "name": "configs", + "internalType": "struct PythOracle.TokenConfig[]", + "name": "tokenConfigs_", "type": "tuple[]" } ], @@ -57488,6 +57019,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "contract IPyth", + "name": "underlyingPythOracle_", + "type": "address" + } + ], + "name": "setUnderlyingPythOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -57499,34 +57043,19 @@ "name": "tokenConfigs", "outputs": [ { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "baseUnit", - "type": "uint256" + "internalType": "bytes32", + "name": "pythId", + "type": "bytes32" }, { "internalType": "address", - "name": "pancakePool", + "name": "asset", "type": "address" }, { - "internalType": "bool", - "name": "isBnbBased", - "type": "bool" - }, - { - "internalType": "bool", - "name": "isReversedPool", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "anchorPeriod", - "type": "uint256" + "internalType": "uint64", + "name": "maxStalePeriod", + "type": "uint64" } ], "stateMutability": "view", @@ -57546,22 +57075,16 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], - "name": "updateTwap", + "inputs": [], + "name": "underlyingPythOracle", "outputs": [ { - "internalType": "uint256", + "internalType": "contract IPyth", "name": "", - "type": "uint256" + "type": "address" } ], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -57589,30 +57112,11 @@ ], "stateMutability": "view", "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "windowStart", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" } ] }, - "TwapOracle_Proxy": { - "address": "0x3eeE05d929D1E9816185B1b6d8c470eC192b4432", + "PythOracle_Proxy": { + "address": "0x94E1534c14e0736BB24decA625f2F5364B198E0C", "abi": [ { "inputs": [ @@ -57747,8 +57251,8 @@ } ] }, - "GovernorBravoV4": { - "address": "0x4baF88AbA7f86f6540728BEF454b224C5d2215e7", + "RedStoneOracle": { + "address": "0x0Af51d1504ac5B711A9EAFe2fAC11A51d32029Ad", "abi": [ { "anonymous": false, @@ -57756,7 +57260,7 @@ { "indexed": false, "internalType": "address", - "name": "oldAdmin", + "name": "previousAdmin", "type": "address" }, { @@ -57766,157 +57270,132 @@ "type": "address" } ], - "name": "NewAdmin", + "name": "AdminChanged", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "oldGuardian", - "type": "address" - }, - { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "newGuardian", + "name": "beacon", "type": "address" } ], - "name": "NewGuardian", + "name": "BeaconUpgraded", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "oldImplementation", - "type": "address" - }, - { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "newImplementation", + "name": "implementation", "type": "address" } ], - "name": "NewImplementation", + "name": "Upgraded", "type": "event" }, { - "anonymous": false, - "inputs": [ + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ { - "indexed": false, "internalType": "address", - "name": "oldPendingAdmin", + "name": "admin_", "type": "address" - }, + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ { - "indexed": false, "internalType": "address", - "name": "newPendingAdmin", + "name": "implementation_", "type": "address" } ], - "name": "NewPendingAdmin", - "type": "event" + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" + "internalType": "address", + "name": "newImplementation", + "type": "address" } ], - "name": "ProposalCanceled", - "type": "event" + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, "internalType": "address", - "name": "proposer", + "name": "newImplementation", "type": "address" }, { - "indexed": false, - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "string[]", - "name": "signatures", - "type": "string[]" - }, - { - "indexed": false, - "internalType": "bytes[]", - "name": "calldatas", - "type": "bytes[]" - }, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "startBlock", - "type": "uint256" + "internalType": "address", + "name": "sender", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" + "internalType": "address", + "name": "calledContract", + "type": "address" }, { - "indexed": false, "internalType": "string", - "name": "description", + "name": "methodSignature", "type": "string" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "proposalType", - "type": "uint8" } ], - "name": "ProposalCreated", - "type": "event" + "name": "Unauthorized", + "type": "error" }, { "anonymous": false, "inputs": [ { "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "ProposalExecuted", + "name": "Initialized", "type": "event" }, { @@ -57924,56 +57403,56 @@ "inputs": [ { "indexed": false, - "internalType": "uint256", - "name": "oldMaxOperations", - "type": "uint256" + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" }, { "indexed": false, - "internalType": "uint256", - "name": "newMaxOperations", - "type": "uint256" + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" } ], - "name": "ProposalMaxOperationsUpdated", + "name": "NewAccessControlManager", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "eta", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "ProposalQueued", + "name": "OwnershipTransferStarted", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "oldProposalThreshold", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "newProposalThreshold", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "ProposalThresholdSet", + "name": "OwnershipTransferred", "type": "event" }, { @@ -57982,124 +57461,92 @@ { "indexed": true, "internalType": "address", - "name": "voter", + "name": "asset", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "proposalId", + "name": "previousPriceMantissa", "type": "uint256" }, - { - "indexed": false, - "internalType": "uint8", - "name": "support", - "type": "uint8" - }, { "indexed": false, "internalType": "uint256", - "name": "votes", + "name": "newPriceMantissa", "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" } ], - "name": "VoteCast", + "name": "PricePosted", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "oldVotingDelay", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" }, { "indexed": false, - "internalType": "uint256", - "name": "newVotingDelay", - "type": "uint256" - } - ], - "name": "VotingDelaySet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldVotingPeriod", - "type": "uint256" + "internalType": "address", + "name": "feed", + "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "newVotingPeriod", + "name": "maxStalePeriod", "type": "uint256" } ], - "name": "VotingPeriodSet", + "name": "TokenConfigAdded", "type": "event" }, { - "constant": true, "inputs": [], - "name": "BALLOT_TYPEHASH", + "name": "BNB_ADDR", "outputs": [ { - "internalType": "bytes32", + "internalType": "address", "name": "", - "type": "bytes32" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], - "name": "DOMAIN_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], - "name": "MAX_PROPOSAL_THRESHOLD", + "name": "accessControlManager", "outputs": [ { - "internalType": "uint256", + "internalType": "contract IAccessControlManagerV8", "name": "", - "type": "uint256" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "MAX_VOTING_DELAY", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", "outputs": [ { "internalType": "uint256", @@ -58107,59 +57554,57 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "MAX_VOTING_PERIOD", - "outputs": [ + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "address", + "name": "accessControlManager_", + "type": "address" } ], - "payable": false, - "stateMutability": "view", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], - "name": "MIN_PROPOSAL_THRESHOLD", + "name": "owner", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], - "name": "MIN_VOTING_DELAY", + "name": "pendingOwner", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "MIN_VOTING_PERIOD", + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "prices", "outputs": [ { "internalType": "uint256", @@ -58167,755 +57612,711 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [], - "name": "_acceptAdmin", + "name": "renounceOwnership", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", - "name": "governorAlpha", + "name": "accessControlManager_", "type": "address" } ], - "name": "_initiate", + "name": "setAccessControlManager", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", - "name": "newGuardian", + "name": "asset", "type": "address" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" } ], - "name": "_setGuardian", + "name": "setDirectPrice", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "address", - "name": "newPendingAdmin", - "type": "address" + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" } ], - "name": "_setPendingAdmin", + "name": "setTokenConfig", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "uint256", - "name": "proposalMaxOperations_", - "type": "uint256" + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" } ], - "name": "_setProposalMaxOperations", + "name": "setTokenConfigs", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "admin", - "outputs": [ + "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, { "internalType": "uint256", - "name": "proposalId", + "name": "maxStalePeriod", "type": "uint256" } ], - "name": "cancel", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "support", - "type": "uint8" + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "castVote", + "name": "transferOwnership", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "support", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" + "internalType": "address", + "name": "_logic", + "type": "address" }, { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" + "internalType": "address", + "name": "admin_", + "type": "address" }, { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "name": "castVoteBySig", - "outputs": [], - "payable": false, + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "RedStoneOracle_Implementation": { + "address": "0xCAC32CFceAe762Bd6DA9C1d24DCB9Ce7FB6C2e73", + "abi": [ + { + "inputs": [], "stateMutability": "nonpayable", - "type": "function" + "type": "constructor" }, { - "constant": false, "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "sender", + "type": "address" }, { - "internalType": "uint8", - "name": "support", - "type": "uint8" + "internalType": "address", + "name": "calledContract", + "type": "address" }, { "internalType": "string", - "name": "reason", + "name": "methodSignature", "type": "string" } ], - "name": "castVoteWithReason", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "name": "Unauthorized", + "type": "error" }, { - "constant": false, + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "execute", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "name": "Initialized", + "type": "event" }, { - "constant": true, + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - } - ], - "name": "getActions", - "outputs": [ - { - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "internalType": "string[]", - "name": "signatures", - "type": "string[]" + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" }, { - "internalType": "bytes[]", - "name": "calldatas", - "type": "bytes[]" + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "NewAccessControlManager", + "type": "event" }, { - "constant": true, + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "voter", + "name": "newOwner", "type": "address" } ], - "name": "getReceipt", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "hasVoted", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "support", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "votes", - "type": "uint96" - } - ], - "internalType": "struct GovernorBravoDelegateStorageV1.Receipt", - "name": "", - "type": "tuple" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "OwnershipTransferStarted", + "type": "event" }, { - "constant": true, - "inputs": [], - "name": "guardian", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "previousOwner", "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "implementation", - "outputs": [ + }, { + "indexed": true, "internalType": "address", - "name": "", + "name": "newOwner", "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "initialProposalId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "OwnershipTransferred", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "xvsVault_", + "name": "asset", "type": "address" }, { - "components": [ - { - "internalType": "uint256", - "name": "votingDelay", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votingPeriod", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalThreshold", - "type": "uint256" - } - ], - "internalType": "struct GovernorBravoDelegateStorageV2.ProposalConfig[]", - "name": "proposalConfigs_", - "type": "tuple[]" - }, - { - "internalType": "contract TimelockInterface[]", - "name": "timelocks", - "type": "address[]" + "indexed": false, + "internalType": "uint256", + "name": "previousPriceMantissa", + "type": "uint256" }, { - "internalType": "address", - "name": "guardian_", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "newPriceMantissa", + "type": "uint256" } ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "name": "PricePosted", + "type": "event" }, { - "constant": true, + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "asset", "type": "address" - } - ], - "name": "latestProposalIds", - "outputs": [ + }, { + "indexed": false, + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "indexed": false, "internalType": "uint256", - "name": "", + "name": "maxStalePeriod", "type": "uint256" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "TokenConfigAdded", + "type": "event" }, { - "constant": true, "inputs": [], - "name": "name", + "name": "BNB_ADDR", "outputs": [ { - "internalType": "string", + "internalType": "address", "name": "", - "type": "string" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], - "name": "pendingAdmin", + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "address", + "name": "asset", + "type": "address" } ], - "name": "proposalConfigs", + "name": "getPrice", "outputs": [ { "internalType": "uint256", - "name": "votingDelay", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votingPeriod", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "proposalThreshold", + "name": "", "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "proposalCount", - "outputs": [ + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "address", + "name": "accessControlManager_", + "type": "address" } ], - "payable": false, - "stateMutability": "view", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], - "name": "proposalMaxOperations", + "name": "owner", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], - "name": "proposalThreshold", + "name": "pendingOwner", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], - "name": "proposalTimelocks", + "name": "prices", "outputs": [ { - "internalType": "contract TimelockInterface", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "address", + "name": "accessControlManager_", + "type": "address" } ], - "name": "proposals", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "proposer", + "name": "asset", "type": "address" }, { "internalType": "uint256", - "name": "eta", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "startBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "forVotes", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "againstVotes", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "abstainVotes", + "name": "price", "type": "uint256" - }, - { - "internalType": "bool", - "name": "canceled", - "type": "bool" - }, - { - "internalType": "bool", - "name": "executed", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "proposalType", - "type": "uint8" } ], - "payable": false, - "stateMutability": "view", + "name": "setDirectPrice", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "internalType": "string[]", - "name": "signatures", - "type": "string[]" - }, + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ { - "internalType": "bytes[]", - "name": "calldatas", - "type": "bytes[]" + "internalType": "address", + "name": "asset", + "type": "address" }, { - "internalType": "string", - "name": "description", - "type": "string" + "internalType": "address", + "name": "feed", + "type": "address" }, - { - "internalType": "enum GovernorBravoDelegateStorageV2.ProposalType", - "name": "proposalType", - "type": "uint8" - } - ], - "name": "propose", - "outputs": [ { "internalType": "uint256", - "name": "", + "name": "maxStalePeriod", "type": "uint256" } ], - "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "queue", + "name": "transferOwnership", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" + } + ] + }, + "RedStoneOracle_Proxy": { + "address": "0x0Af51d1504ac5B711A9EAFe2fAC11A51d32029Ad", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" }, { - "constant": true, - "inputs": [], - "name": "quorumVotes", - "outputs": [ + "anonymous": false, + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "AdminChanged", + "type": "event" }, { - "constant": true, + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" } ], - "name": "state", - "outputs": [ + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "internalType": "enum GovernorBravoDelegateStorageV1.ProposalState", - "name": "", - "type": "uint8" + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" }, { - "constant": true, "inputs": [], - "name": "timelock", + "name": "admin", "outputs": [ { - "internalType": "contract TimelockInterface", - "name": "", + "internalType": "address", + "name": "admin_", "type": "address" } ], - "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], - "name": "votingDelay", + "name": "implementation", "outputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "address", + "name": "implementation_", + "type": "address" } ], - "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "votingPeriod", - "outputs": [ + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "address", + "name": "newImplementation", + "type": "address" } ], - "payable": false, - "stateMutability": "view", + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "xvsVault", - "outputs": [ + "inputs": [ { - "internalType": "contract XvsVaultInterface", - "name": "", + "internalType": "address", + "name": "newImplementation", "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "payable": false, - "stateMutability": "view", + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" } ] }, - "PegStability_USDT": { - "address": "0xB21E69eef4Bc1D64903fa28D9b32491B1c0786F1", + "ResilientOracle": { + "address": "0x3cD69251D04A28d887Ac14cbe2E14c52F3D57823", "abi": [ { "anonymous": false, @@ -58979,19 +58380,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "implementation", @@ -59040,41 +58428,6 @@ "stateMutability": "payable", "type": "receive" }, - { - "inputs": [], - "name": "AlreadyPaused", - "type": "error" - }, - { - "inputs": [], - "name": "AmountTooSmall", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFee", - "type": "error" - }, - { - "inputs": [], - "name": "NotEnoughVAI", - "type": "error" - }, - { - "inputs": [], - "name": "NotPaused", - "type": "error" - }, - { - "inputs": [], - "name": "Paused", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyDecimals", - "type": "error" - }, { "inputs": [ { @@ -59096,69 +58449,6 @@ "name": "Unauthorized", "type": "error" }, - { - "inputs": [], - "name": "VAIMintCapReached", - "type": "error" - }, - { - "inputs": [], - "name": "VAIMintedUnderflow", - "type": "error" - }, - { - "inputs": [], - "name": "VAITransferFail", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAmount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldFeeIn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newFeeIn", - "type": "uint256" - } - ], - "name": "FeeInChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldFeeOut", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newFeeOut", - "type": "uint256" - } - ], - "name": "FeeOutChanged", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -59197,17 +58487,23 @@ { "indexed": true, "internalType": "address", - "name": "oldOracle", + "name": "asset", "type": "address" }, { "indexed": true, - "internalType": "address", - "name": "newOracle", - "type": "address" + "internalType": "uint256", + "name": "role", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "enable", + "type": "bool" } ], - "name": "OracleChanged", + "name": "OracleEnabled", "type": "event" }, { @@ -59216,17 +58512,23 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "asset", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "oracle", "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "role", + "type": "uint256" } ], - "name": "OwnershipTransferStarted", + "name": "OracleSet", "type": "event" }, { @@ -59245,7 +58547,7 @@ "type": "address" } ], - "name": "OwnershipTransferred", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -59254,24 +58556,17 @@ { "indexed": true, "internalType": "address", - "name": "admin", + "name": "previousOwner", "type": "address" - } - ], - "name": "PSMPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { "indexed": true, "internalType": "address", - "name": "admin", + "name": "newOwner", "type": "address" } ], - "name": "PSMResumed", + "name": "OwnershipTransferred", "type": "event" }, { @@ -59279,97 +58574,66 @@ "inputs": [ { "indexed": false, - "internalType": "uint256", - "name": "stableIn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "vaiOut", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fee", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "StableForVAISwapped", + "name": "Paused", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "vaiBurnt", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "stableOut", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "mainOracle", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "vaiFee", - "type": "uint256" - } - ], - "name": "VAIForStableSwapped", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldCap", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "pivotOracle", + "type": "address" }, { "indexed": false, - "internalType": "uint256", - "name": "newCap", - "type": "uint256" + "internalType": "address", + "name": "fallbackOracle", + "type": "address" } ], - "name": "VAIMintCapChanged", + "name": "TokenConfigAdded", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "oldTreasury", - "type": "address" - }, - { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newTreasury", + "name": "account", "type": "address" } ], - "name": "VenusTreasuryChanged", + "name": "Unpaused", "type": "event" }, { "inputs": [], - "name": "BASIS_POINTS_DIVISOR", + "name": "BNB_ADDR", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -59377,7 +58641,7 @@ }, { "inputs": [], - "name": "MANTISSA_ONE", + "name": "INVALID_PRICE", "outputs": [ { "internalType": "uint256", @@ -59390,23 +58654,17 @@ }, { "inputs": [], - "name": "ONE_DOLLAR", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "STABLE_TOKEN_ADDRESS", + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -59416,10 +58674,10 @@ }, { "inputs": [], - "name": "VAI", + "name": "boundValidator", "outputs": [ { - "internalType": "contract IVAI", + "internalType": "contract BoundValidatorInterface", "name": "", "type": "address" } @@ -59428,28 +58686,66 @@ "type": "function" }, { - "inputs": [], - "name": "acceptOwnership", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "enableOracle", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "accessControlManager", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + } + ], + "name": "getOracle", "outputs": [ { - "internalType": "contract IAccessControlManagerV8", - "name": "", + "internalType": "address", + "name": "oracle", "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "feeIn", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", "outputs": [ { "internalType": "uint256", @@ -59461,13 +58757,36 @@ "type": "function" }, { - "inputs": [], - "name": "feeOut", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getTokenConfig", "outputs": [ { - "internalType": "uint256", + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", "name": "", - "type": "uint256" + "type": "tuple" } ], "stateMutability": "view", @@ -59477,64 +58796,32 @@ "inputs": [ { "internalType": "address", - "name": "accessControlManager_", - "type": "address" - }, - { - "internalType": "address", - "name": "venusTreasury_", - "type": "address" - }, - { - "internalType": "address", - "name": "oracleAddress_", + "name": "vToken", "type": "address" - }, - { - "internalType": "uint256", - "name": "feeIn_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "feeOut_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vaiMintCap_", - "type": "uint256" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "isPaused", + "name": "getUnderlyingPrice", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "oracle", - "outputs": [ + "inputs": [ { - "internalType": "contract ResilientOracleInterface", - "name": "", + "internalType": "address", + "name": "accessControlManager_", "type": "address" } ], - "stateMutability": "view", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { @@ -59559,50 +58846,25 @@ }, { "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "stableTknAmount", - "type": "uint256" - } - ], - "name": "previewSwapStableForVAI", + "name": "paused", "outputs": [ { - "internalType": "uint256", + "internalType": "bool", "name": "", - "type": "uint256" + "type": "bool" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "stableTknAmount", - "type": "uint256" - } - ], - "name": "previewSwapVAIForStable", + "inputs": [], + "name": "pendingOwner", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -59615,13 +58877,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "resume", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -59638,25 +58893,22 @@ { "inputs": [ { - "internalType": "uint256", - "name": "feeIn_", - "type": "uint256" - } - ], - "name": "setFeeIn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "internalType": "address", + "name": "asset", + "type": "address" + }, { - "internalType": "uint256", - "name": "feeOut_", - "type": "uint256" + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" } ], - "name": "setFeeOut", + "name": "setOracle", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -59664,12 +58916,29 @@ { "inputs": [ { - "internalType": "address", - "name": "oracleAddress_", - "type": "address" + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" } ], - "name": "setOracle", + "name": "setTokenConfig", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -59677,12 +58946,29 @@ { "inputs": [ { - "internalType": "uint256", - "name": "vaiMintCap_", - "type": "uint256" + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" } ], - "name": "setVAIMintCap", + "name": "setTokenConfigs", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -59691,36 +58977,19 @@ "inputs": [ { "internalType": "address", - "name": "venusTreasury_", + "name": "newOwner", "type": "address" } ], - "name": "setVenusTreasury", + "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "uint256", - "name": "stableTknAmount", - "type": "uint256" - } - ], - "name": "swapStableForVAI", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "inputs": [], + "name": "unpause", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -59728,23 +58997,12 @@ "inputs": [ { "internalType": "address", - "name": "receiver", + "name": "asset", "type": "address" - }, - { - "internalType": "uint256", - "name": "stableTknAmount", - "type": "uint256" - } - ], - "name": "swapVAIForStable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" } ], + "name": "updateAssetPrice", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -59752,36 +59010,23 @@ "inputs": [ { "internalType": "address", - "name": "newOwner", + "name": "vToken", "type": "address" } ], - "name": "transferOwnership", + "name": "updatePrice", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "vaiMintCap", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "vaiMinted", + "name": "vBnb", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -59789,7 +59034,7 @@ }, { "inputs": [], - "name": "venusTreasury", + "name": "vai", "outputs": [ { "internalType": "address", @@ -59823,60 +59068,30 @@ } ] }, - "PegStability_USDT_Implementation": { - "address": "0xDDa903294fB71141302aD3Bf2AF37dD6Cbd5DBbF", + "ResilientOracle_Implementation": { + "address": "0x35cC3b99985F9d970aEcc9BD83d5Ac78a074a896", "abi": [ { "inputs": [ { "internalType": "address", - "name": "stableTokenAddress_", + "name": "vBnbAddress", "type": "address" }, { "internalType": "address", - "name": "vaiAddress_", + "name": "vaiAddress", + "type": "address" + }, + { + "internalType": "contract BoundValidatorInterface", + "name": "_boundValidator", "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, - { - "inputs": [], - "name": "AlreadyPaused", - "type": "error" - }, - { - "inputs": [], - "name": "AmountTooSmall", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFee", - "type": "error" - }, - { - "inputs": [], - "name": "NotEnoughVAI", - "type": "error" - }, - { - "inputs": [], - "name": "NotPaused", - "type": "error" - }, - { - "inputs": [], - "name": "Paused", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyDecimals", - "type": "error" - }, { "inputs": [ { @@ -59898,69 +59113,6 @@ "name": "Unauthorized", "type": "error" }, - { - "inputs": [], - "name": "VAIMintCapReached", - "type": "error" - }, - { - "inputs": [], - "name": "VAIMintedUnderflow", - "type": "error" - }, - { - "inputs": [], - "name": "VAITransferFail", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAmount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldFeeIn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newFeeIn", - "type": "uint256" - } - ], - "name": "FeeInChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldFeeOut", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newFeeOut", - "type": "uint256" - } - ], - "name": "FeeOutChanged", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -59999,17 +59151,23 @@ { "indexed": true, "internalType": "address", - "name": "oldOracle", + "name": "asset", "type": "address" }, { "indexed": true, - "internalType": "address", - "name": "newOracle", - "type": "address" + "internalType": "uint256", + "name": "role", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "enable", + "type": "bool" } ], - "name": "OracleChanged", + "name": "OracleEnabled", "type": "event" }, { @@ -60018,17 +59176,23 @@ { "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "asset", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "oracle", "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "role", + "type": "uint256" } ], - "name": "OwnershipTransferStarted", + "name": "OracleSet", "type": "event" }, { @@ -60047,7 +59211,7 @@ "type": "address" } ], - "name": "OwnershipTransferred", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -60056,24 +59220,17 @@ { "indexed": true, "internalType": "address", - "name": "admin", + "name": "previousOwner", "type": "address" - } - ], - "name": "PSMPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { "indexed": true, "internalType": "address", - "name": "admin", + "name": "newOwner", "type": "address" } ], - "name": "PSMResumed", + "name": "OwnershipTransferred", "type": "event" }, { @@ -60081,97 +59238,66 @@ "inputs": [ { "indexed": false, - "internalType": "uint256", - "name": "stableIn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "vaiOut", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fee", - "type": "uint256" + "internalType": "address", + "name": "account", + "type": "address" } ], - "name": "StableForVAISwapped", + "name": "Paused", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "vaiBurnt", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "stableOut", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "mainOracle", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "vaiFee", - "type": "uint256" - } - ], - "name": "VAIForStableSwapped", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldCap", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "pivotOracle", + "type": "address" }, { "indexed": false, - "internalType": "uint256", - "name": "newCap", - "type": "uint256" + "internalType": "address", + "name": "fallbackOracle", + "type": "address" } ], - "name": "VAIMintCapChanged", + "name": "TokenConfigAdded", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "oldTreasury", - "type": "address" - }, - { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newTreasury", + "name": "account", "type": "address" } ], - "name": "VenusTreasuryChanged", + "name": "Unpaused", "type": "event" }, { "inputs": [], - "name": "BASIS_POINTS_DIVISOR", + "name": "BNB_ADDR", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -60179,7 +59305,7 @@ }, { "inputs": [], - "name": "MANTISSA_ONE", + "name": "INVALID_PRICE", "outputs": [ { "internalType": "uint256", @@ -60192,23 +59318,17 @@ }, { "inputs": [], - "name": "ONE_DOLLAR", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "STABLE_TOKEN_ADDRESS", + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -60218,10 +59338,10 @@ }, { "inputs": [], - "name": "VAI", + "name": "boundValidator", "outputs": [ { - "internalType": "contract IVAI", + "internalType": "contract BoundValidatorInterface", "name": "", "type": "address" } @@ -60230,28 +59350,66 @@ "type": "function" }, { - "inputs": [], - "name": "acceptOwnership", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "enableOracle", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "accessControlManager", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + } + ], + "name": "getOracle", "outputs": [ { - "internalType": "contract IAccessControlManagerV8", - "name": "", + "internalType": "address", + "name": "oracle", "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "feeIn", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", "outputs": [ { "internalType": "uint256", @@ -60263,13 +59421,36 @@ "type": "function" }, { - "inputs": [], - "name": "feeOut", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getTokenConfig", "outputs": [ { - "internalType": "uint256", + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", "name": "", - "type": "uint256" + "type": "tuple" } ], "stateMutability": "view", @@ -60279,64 +59460,32 @@ "inputs": [ { "internalType": "address", - "name": "accessControlManager_", - "type": "address" - }, - { - "internalType": "address", - "name": "venusTreasury_", - "type": "address" - }, - { - "internalType": "address", - "name": "oracleAddress_", + "name": "vToken", "type": "address" - }, - { - "internalType": "uint256", - "name": "feeIn_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "feeOut_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "vaiMintCap_", - "type": "uint256" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "isPaused", + "name": "getUnderlyingPrice", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "oracle", - "outputs": [ + "inputs": [ { - "internalType": "contract ResilientOracleInterface", - "name": "", + "internalType": "address", + "name": "accessControlManager_", "type": "address" } ], - "stateMutability": "view", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { @@ -60361,50 +59510,25 @@ }, { "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "stableTknAmount", - "type": "uint256" - } - ], - "name": "previewSwapStableForVAI", + "name": "paused", "outputs": [ { - "internalType": "uint256", + "internalType": "bool", "name": "", - "type": "uint256" + "type": "bool" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "stableTknAmount", - "type": "uint256" - } - ], - "name": "previewSwapVAIForStable", + "inputs": [], + "name": "pendingOwner", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -60417,13 +59541,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "resume", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -60440,12 +59557,22 @@ { "inputs": [ { - "internalType": "uint256", - "name": "feeIn_", - "type": "uint256" + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" } ], - "name": "setFeeIn", + "name": "setOracle", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -60453,12 +59580,29 @@ { "inputs": [ { - "internalType": "uint256", - "name": "feeOut_", - "type": "uint256" + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" } ], - "name": "setFeeOut", + "name": "setTokenConfig", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -60466,25 +59610,29 @@ { "inputs": [ { - "internalType": "address", - "name": "oracleAddress_", - "type": "address" + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" } ], - "name": "setOracle", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "vaiMintCap_", - "type": "uint256" - } - ], - "name": "setVAIMintCap", + "name": "setTokenConfigs", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -60493,36 +59641,19 @@ "inputs": [ { "internalType": "address", - "name": "venusTreasury_", + "name": "newOwner", "type": "address" } ], - "name": "setVenusTreasury", + "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "uint256", - "name": "stableTknAmount", - "type": "uint256" - } - ], - "name": "swapStableForVAI", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "inputs": [], + "name": "unpause", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -60530,23 +59661,12 @@ "inputs": [ { "internalType": "address", - "name": "receiver", + "name": "asset", "type": "address" - }, - { - "internalType": "uint256", - "name": "stableTknAmount", - "type": "uint256" - } - ], - "name": "swapVAIForStable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" } ], + "name": "updateAssetPrice", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -60554,36 +59674,23 @@ "inputs": [ { "internalType": "address", - "name": "newOwner", + "name": "vToken", "type": "address" } ], - "name": "transferOwnership", + "name": "updatePrice", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "vaiMintCap", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "vaiMinted", + "name": "vBnb", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -60591,7 +59698,7 @@ }, { "inputs": [], - "name": "venusTreasury", + "name": "vai", "outputs": [ { "internalType": "address", @@ -60604,8 +59711,8 @@ } ] }, - "PegStability_USDT_Proxy": { - "address": "0xB21E69eef4Bc1D64903fa28D9b32491B1c0786F1", + "ResilientOracle_Proxy": { + "address": "0x3cD69251D04A28d887Ac14cbe2E14c52F3D57823", "abi": [ { "inputs": [ @@ -60690,19 +59797,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "implementation", @@ -60753,123 +59847,201 @@ } ] }, - "Timelock_Critical": { - "address": "0x23B893a7C45a5Eb8c8C062b9F32d0D2e43eD286D", + "TwapOracle": { + "address": "0x3eeE05d929D1E9816185B1b6d8c470eC192b4432", "abi": [ { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "admin_", + "name": "previousAdmin", "type": "address" }, { - "internalType": "uint256", - "name": "delay_", - "type": "uint256" + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" + "name": "AdminChanged", + "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, "internalType": "address", - "name": "target", + "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": [], + "name": "implementation", + "outputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "indexed": false, - "internalType": "string", - "name": "signature", - "type": "string" + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" }, { - "indexed": false, "internalType": "bytes", "name": "data", "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "eta", - "type": "uint256" + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "name": "CancelTransaction", - "type": "event" + "name": "Unauthorized", + "type": "error" }, { "anonymous": false, "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, { "indexed": true, "internalType": "address", - "name": "target", + "name": "asset", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "value", + "name": "price", "type": "uint256" }, { "indexed": false, - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "oldTimestamp", + "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "eta", + "name": "newTimestamp", "type": "uint256" } ], - "name": "ExecuteTransaction", + "name": "AnchorPriceUpdated", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", "type": "address" } ], - "name": "NewAdmin", + "name": "NewAccessControlManager", "type": "event" }, { @@ -60877,12 +60049,18 @@ "inputs": [ { "indexed": true, - "internalType": "uint256", - "name": "newDelay", - "type": "uint256" + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "NewDelay", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -60891,11 +60069,17 @@ { "indexed": true, "internalType": "address", - "name": "newPendingAdmin", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", "type": "address" } ], - "name": "NewPendingAdmin", + "name": "OwnershipTransferred", "type": "event" }, { @@ -60903,53 +60087,66 @@ "inputs": [ { "indexed": true, - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pancakePool", + "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "anchorPeriod", + "type": "uint256" + } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, "internalType": "address", - "name": "target", + "name": "asset", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "value", + "name": "oldTimestamp", "type": "uint256" }, { "indexed": false, - "internalType": "string", - "name": "signature", - "type": "string" + "internalType": "uint256", + "name": "oldAcc", + "type": "uint256" }, { "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "newTimestamp", + "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "eta", + "name": "newAcc", "type": "uint256" } ], - "name": "QueueTransaction", + "name": "TwapWindowUpdated", "type": "event" }, { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "constant": true, "inputs": [], - "name": "GRACE_PERIOD", + "name": "BNB_BASE_UNIT", "outputs": [ { "internalType": "uint256", @@ -60957,14 +60154,12 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], - "name": "MAXIMUM_DELAY", + "name": "BUSD_BASE_UNIT", "outputs": [ { "internalType": "uint256", @@ -60972,88 +60167,83 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], - "name": "MINIMUM_DELAY", + "name": "WBNB", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [], - "name": "acceptAdmin", + "name": "acceptOwnership", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], - "name": "admin", + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "eta", - "type": "uint256" + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "baseUnit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "pancakePool", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBnbBased", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isReversedPool", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "anchorPeriod", + "type": "uint256" + } + ], + "internalType": "struct TwapOracle.TokenConfig", + "name": "config", + "type": "tuple" } ], - "name": "cancelTransaction", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "delay", + "name": "currentCumulativePrice", "outputs": [ { "internalType": "uint256", @@ -61061,277 +60251,475 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", - "name": "target", + "name": "vToken", "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "eta", - "type": "uint256" } ], - "name": "executeTransaction", + "name": "getUnderlyingPrice", "outputs": [ { - "internalType": "bytes", + "internalType": "uint256", "name": "", - "type": "bytes" + "type": "uint256" } ], - "payable": true, - "stateMutability": "payable", + "stateMutability": "view", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "pendingAdmin", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "accessControlManager_", "type": "address" } ], - "payable": false, - "stateMutability": "view", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", - "name": "target", + "name": "", "type": "address" }, { "internalType": "uint256", - "name": "value", + "name": "", "type": "uint256" - }, - { - "internalType": "string", - "name": "signature", - "type": "string" - }, + } + ], + "name": "observations", + "outputs": [ { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" }, { "internalType": "uint256", - "name": "eta", + "name": "acc", "type": "uint256" } ], - "name": "queueTransaction", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", "outputs": [ { - "internalType": "bytes32", + "internalType": "address", "name": "", - "type": "bytes32" + "type": "address" } ], - "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": true, - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "queuedTransactions", + "inputs": [], + "name": "pendingOwner", "outputs": [ { - "internalType": "bool", + "internalType": "address", "name": "", - "type": "bool" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "uint256", - "name": "delay_", + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "prices", + "outputs": [ + { + "internalType": "uint256", + "name": "", "type": "uint256" } ], - "name": "setDelay", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", - "name": "pendingAdmin_", + "name": "accessControlManager_", "type": "address" } ], - "name": "setPendingAdmin", + "name": "setAccessControlManager", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" - } - ] - }, - "Timelock_FastTrack": { - "address": "0x3CFf21b7AF8390fE68799D58727d3b4C25a83cb6", - "abi": [ + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "baseUnit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "pancakePool", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBnbBased", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isReversedPool", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "anchorPeriod", + "type": "uint256" + } + ], + "internalType": "struct TwapOracle.TokenConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "baseUnit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "pancakePool", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBnbBased", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isReversedPool", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "anchorPeriod", + "type": "uint256" + } + ], + "internalType": "struct TwapOracle.TokenConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { "internalType": "address", - "name": "admin_", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "baseUnit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "pancakePool", "type": "address" }, + { + "internalType": "bool", + "name": "isBnbBased", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isReversedPool", + "type": "bool" + }, { "internalType": "uint256", - "name": "delay_", + "name": "anchorPeriod", "type": "uint256" } ], - "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], "stateMutability": "nonpayable", - "type": "constructor" + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updateTwap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBnb", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "target", + "name": "", "type": "address" - }, + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vai", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "windowStart", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "value", + "name": "", "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" }, { - "indexed": false, - "internalType": "string", - "name": "signature", - "type": "string" + "internalType": "address", + "name": "admin_", + "type": "address" }, { - "indexed": false, "internalType": "bytes", - "name": "data", + "name": "_data", "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "TwapOracle_Implementation": { + "address": "0x572ec272B4Ae3a50B99905AFd78671F84474ffd1", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "vBnbAddress", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "eta", - "type": "uint256" + "internalType": "address", + "name": "wBnbAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "vaiAddress", + "type": "address" } ], - "name": "CancelTransaction", - "type": "event" + "stateMutability": "nonpayable", + "type": "constructor" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" + "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": "target", + "name": "asset", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "value", + "name": "price", "type": "uint256" }, { "indexed": false, - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "oldTimestamp", + "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "eta", + "name": "newTimestamp", "type": "uint256" } ], - "name": "ExecuteTransaction", + "name": "AnchorPriceUpdated", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, "internalType": "address", - "name": "newAdmin", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", "type": "address" } ], - "name": "NewAdmin", + "name": "NewAccessControlManager", "type": "event" }, { @@ -61339,12 +60727,18 @@ "inputs": [ { "indexed": true, - "internalType": "uint256", - "name": "newDelay", - "type": "uint256" + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "name": "NewDelay", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -61353,11 +60747,17 @@ { "indexed": true, "internalType": "address", - "name": "newPendingAdmin", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", "type": "address" } ], - "name": "NewPendingAdmin", + "name": "OwnershipTransferred", "type": "event" }, { @@ -61365,53 +60765,66 @@ "inputs": [ { "indexed": true, - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pancakePool", + "type": "address" }, + { + "indexed": true, + "internalType": "uint256", + "name": "anchorPeriod", + "type": "uint256" + } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, "internalType": "address", - "name": "target", + "name": "asset", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "value", + "name": "oldTimestamp", "type": "uint256" }, { "indexed": false, - "internalType": "string", - "name": "signature", - "type": "string" + "internalType": "uint256", + "name": "oldAcc", + "type": "uint256" }, { "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "uint256", + "name": "newTimestamp", + "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "eta", + "name": "newAcc", "type": "uint256" } ], - "name": "QueueTransaction", + "name": "TwapWindowUpdated", "type": "event" }, { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "constant": true, "inputs": [], - "name": "GRACE_PERIOD", + "name": "BNB_BASE_UNIT", "outputs": [ { "internalType": "uint256", @@ -61419,14 +60832,12 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], - "name": "MAXIMUM_DELAY", + "name": "BUSD_BASE_UNIT", "outputs": [ { "internalType": "uint256", @@ -61434,88 +60845,102 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], - "name": "MINIMUM_DELAY", + "name": "WBNB", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [], - "name": "acceptAdmin", + "name": "acceptOwnership", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], - "name": "admin", + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "baseUnit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "pancakePool", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBnbBased", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isReversedPool", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "anchorPeriod", + "type": "uint256" + } + ], + "internalType": "struct TwapOracle.TokenConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "currentCumulativePrice", + "outputs": [ { "internalType": "uint256", - "name": "eta", + "name": "", "type": "uint256" } ], - "name": "cancelTransaction", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "delay", + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", "outputs": [ { "internalType": "uint256", @@ -61523,55 +60948,54 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", - "name": "target", + "name": "accessControlManager_", "type": "address" - }, + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "address", + "name": "", + "type": "address" }, { "internalType": "uint256", - "name": "eta", + "name": "", "type": "uint256" } ], - "name": "executeTransaction", + "name": "observations", "outputs": [ { - "internalType": "bytes", - "name": "", - "type": "bytes" + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "acc", + "type": "uint256" } ], - "payable": true, - "stateMutability": "payable", + "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], - "name": "pendingAdmin", + "name": "owner", "outputs": [ { "internalType": "address", @@ -61579,943 +61003,132721 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "eta", - "type": "uint256" - } - ], - "name": "queueTransaction", + "inputs": [], + "name": "pendingOwner", "outputs": [ { - "internalType": "bytes32", + "internalType": "address", "name": "", - "type": "bytes32" + "type": "address" } ], - "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { - "internalType": "bytes32", + "internalType": "address", "name": "", - "type": "bytes32" + "type": "address" } ], - "name": "queuedTransactions", + "name": "prices", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "delay_", - "type": "uint256" - } - ], - "name": "setDelay", + "inputs": [], + "name": "renounceOwnership", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", - "name": "pendingAdmin_", + "name": "accessControlManager_", "type": "address" } ], - "name": "setPendingAdmin", + "name": "setAccessControlManager", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" - } - ] - }, - "VenusLens": { - "address": "0x11c8dC3DcA87E8205ec01e6d79Be9442d31701d3", - "abi": [ - { - "constant": true, - "inputs": [], - "name": "BLOCKS_PER_DAY", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" }, { - "constant": true, "inputs": [ - { - "internalType": "contract ComptrollerInterface", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "getAccountLimits", - "outputs": [ { "components": [ { - "internalType": "contract VToken[]", - "name": "markets", - "type": "address[]" + "internalType": "address", + "name": "asset", + "type": "address" }, { "internalType": "uint256", - "name": "liquidity", + "name": "baseUnit", "type": "uint256" }, + { + "internalType": "address", + "name": "pancakePool", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBnbBased", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isReversedPool", + "type": "bool" + }, { "internalType": "uint256", - "name": "shortfall", + "name": "anchorPeriod", "type": "uint256" } ], - "internalType": "struct VenusLens.AccountLimits", - "name": "", + "internalType": "struct TwapOracle.TokenConfig", + "name": "config", "type": "tuple" } ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address payable", - "name": "account", - "type": "address" - }, - { - "internalType": "address", - "name": "comptrollerAddress", - "type": "address" - } - ], - "name": "getDailyXVS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, + "name": "setTokenConfig", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [ - { - "internalType": "contract GovernorAlpha", - "name": "governor", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "proposalIds", - "type": "uint256[]" - } - ], - "name": "getGovProposals", - "outputs": [ { "components": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, { "internalType": "address", - "name": "proposer", + "name": "asset", "type": "address" }, { "internalType": "uint256", - "name": "eta", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "values", - "type": "uint256[]" - }, - { - "internalType": "string[]", - "name": "signatures", - "type": "string[]" - }, - { - "internalType": "bytes[]", - "name": "calldatas", - "type": "bytes[]" - }, - { - "internalType": "uint256", - "name": "startBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "forVotes", + "name": "baseUnit", "type": "uint256" }, { - "internalType": "uint256", - "name": "againstVotes", - "type": "uint256" + "internalType": "address", + "name": "pancakePool", + "type": "address" }, { "internalType": "bool", - "name": "canceled", + "name": "isBnbBased", "type": "bool" }, { "internalType": "bool", - "name": "executed", + "name": "isReversedPool", "type": "bool" + }, + { + "internalType": "uint256", + "name": "anchorPeriod", + "type": "uint256" } ], - "internalType": "struct VenusLens.GovProposal[]", - "name": "", + "internalType": "struct TwapOracle.TokenConfig[]", + "name": "configs", "type": "tuple[]" } ], - "payable": false, - "stateMutability": "view", + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [ { - "internalType": "contract GovernorAlpha", - "name": "governor", + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", "type": "address" }, + { + "internalType": "uint256", + "name": "baseUnit", + "type": "uint256" + }, { "internalType": "address", - "name": "voter", + "name": "pancakePool", "type": "address" }, { - "internalType": "uint256[]", - "name": "proposalIds", - "type": "uint256[]" - } - ], - "name": "getGovReceipts", - "outputs": [ + "internalType": "bool", + "name": "isBnbBased", + "type": "bool" + }, { - "components": [ - { - "internalType": "uint256", - "name": "proposalId", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "hasVoted", - "type": "bool" - }, - { - "internalType": "bool", - "name": "support", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "votes", - "type": "uint96" - } - ], - "internalType": "struct VenusLens.GovReceipt[]", - "name": "", - "type": "tuple[]" + "internalType": "bool", + "name": "isReversedPool", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "anchorPeriod", + "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { - "internalType": "contract XVS", - "name": "xvs", + "internalType": "address", + "name": "newOwner", "type": "address" - }, + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "account", + "name": "vToken", "type": "address" - }, + } + ], + "name": "updateTwap", + "outputs": [ { - "internalType": "uint32[]", - "name": "blockNumbers", - "type": "uint32[]" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "getVenusVotes", + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBnb", "outputs": [ { - "components": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votes", - "type": "uint256" - } - ], - "internalType": "struct VenusLens.VenusVotes[]", + "internalType": "address", "name": "", - "type": "tuple[]" + "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, - "inputs": [ + "inputs": [], + "name": "vai", + "outputs": [ { - "internalType": "contract XVS", - "name": "xvs", + "internalType": "address", + "name": "", "type": "address" - }, + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "account", + "name": "", "type": "address" } ], - "name": "getXVSBalanceMetadata", + "name": "windowStart", "outputs": [ { - "components": [ - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votes", - "type": "uint256" - }, - { - "internalType": "address", - "name": "delegate", - "type": "address" - } - ], - "internalType": "struct VenusLens.XVSBalanceMetadata", + "internalType": "uint256", "name": "", - "type": "tuple" + "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" - }, + } + ] + }, + "TwapOracle_Proxy": { + "address": "0x3eeE05d929D1E9816185B1b6d8c470eC192b4432", + "abi": [ { - "constant": false, "inputs": [ { - "internalType": "contract XVS", - "name": "xvs", - "type": "address" - }, - { - "internalType": "contract ComptrollerInterface", - "name": "comptroller", + "internalType": "address", + "name": "_logic", "type": "address" }, { "internalType": "address", - "name": "account", + "name": "admin_", "type": "address" - } - ], - "name": "getXVSBalanceMetadataExt", - "outputs": [ + }, { - "components": [ - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "votes", - "type": "uint256" - }, - { - "internalType": "address", - "name": "delegate", - "type": "address" - }, - { - "internalType": "uint256", - "name": "allocated", - "type": "uint256" - } - ], - "internalType": "struct VenusLens.XVSBalanceMetadataExt", - "name": "", - "type": "tuple" + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "stateMutability": "payable", + "type": "constructor" }, { - "constant": true, + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "holder", + "name": "previousAdmin", "type": "address" }, { - "internalType": "contract ComptrollerInterface", - "name": "comptroller", + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "name": "pendingRewards", - "outputs": [ + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "components": [ - { - "internalType": "address", - "name": "distributorAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "rewardTokenAddress", - "type": "address" + "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": [], + "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" + } + ] + }, + "AccessControlManagerMockTest": { + "address": "0x4eA05Cb383a258212C46D19299d6e7F14D79fDEC", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "isAllowedToCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "BTCB": { + "address": "0xA808e341e8e723DC6BA0Bb5204Bafc2330d7B8e4", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": 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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "_decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "BUSD": { + "address": "0x8301F2213c0eeD49a7E28Ae4c3e91722919B8B47", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initialAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_tokenName", + "type": "string" + }, + { + "internalType": "uint8", + "name": "_decimalUnits", + "type": "uint8" + }, + { + "internalType": "string", + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "Comptroller": { + "address": "0xfd301ad2503b25a7670a45b11a043c20b04ee896", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "action", + "type": "string" + }, + { + "indexed": false, + "internalType": "bool", + "name": "pauseState", + "type": "bool" + } + ], + "name": "ActionPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "action", + "type": "string" + }, + { + "indexed": false, + "internalType": "bool", + "name": "pauseState", + "type": "bool" + } + ], + "name": "ActionPausedMarket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "ActionProtocolPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vaiMinter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusVAIMintIndex", + "type": "uint256" + } + ], + "name": "DistributedVAIMinterVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributedVAIVaultVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBorrowCap", + "type": "uint256" + } + ], + "name": "NewBorrowCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldBorrowCapGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newBorrowCapGuardian", + "type": "address" + } + ], + "name": "NewBorrowCapGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldComptrollerLens", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newComptrollerLens", + "type": "address" + } + ], + "name": "NewComptrollerLens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldLiquidatorContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newLiquidatorContract", + "type": "address" + } + ], + "name": "NewLiquidatorContract", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract PriceOracle", + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract PriceOracle", + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + } + ], + "name": "NewTreasuryAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + } + ], + "name": "NewTreasuryGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTreasuryPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "NewTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "oldVAIController", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "newVAIController", + "type": "address" + } + ], + "name": "NewVAIController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVAIMintRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "NewVAIMintRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseInterval_", + "type": "uint256" + } + ], + "name": "NewVAIVaultInfo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVenusVAIRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVenusVAIRate", + "type": "uint256" + } + ], + "name": "NewVenusVAIRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVenusVAIVaultRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVenusVAIVaultRate", + "type": "uint256" + } + ], + "name": "NewVenusVAIVaultRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "VenusGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "VenusSpeedUpdated", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract Unitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_borrowGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "_grantXVS", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_mintGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newBorrowCapGuardian", + "type": "address" + } + ], + "name": "_setBorrowCapGuardian", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "comptrollerLens_", + "type": "address" + } + ], + "name": "_setComptrollerLens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newLiquidatorContract_", + "type": "address" + } + ], + "name": "_setLiquidatorContract", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "_setMarketBorrowCaps", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "_setPauseGuardian", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract PriceOracle", + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "_setProtocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + }, + { + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "_setTreasuryData", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "vaiController_", + "type": "address" + } + ], + "name": "_setVAIController", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "_setVAIMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minReleaseAmount_", + "type": "uint256" + } + ], + "name": "_setVAIVaultInfo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "venusSpeed", + "type": "uint256" + } + ], + "name": "_setVenusSpeed", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "venusVAIVaultRate_", + "type": "uint256" + } + ], + "name": "_setVenusVAIVaultRate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "borrowers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "suppliers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "collateral", + "type": "bool" + } + ], + "name": "claimVenus", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimVenus", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimVenus", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "borrowers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "suppliers", + "type": "bool" + } + ], + "name": "claimVenus", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimVenusAsCollateral", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getAllMarkets", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenModify", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "getHypotheticalAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getXVSAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getXVSVTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastContributorBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateVAICalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualMintAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract PriceOracle", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "releaseToVault", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "seizeGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setMintedVAIOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "transferGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusContributorSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "ComptrollerLens": { + "address": "0xc698edFbac7F4A3A2A06757860938e73260ed7a4", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vTokenModify", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "getHypotheticalAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateVAICalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "ETH": { + "address": "0x98f7A83361F7Ac8765CcEBAB1425da6b341958a7", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": 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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "_decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "LTC": { + "address": "0x969F147B6b8D81f86175de33206A4FD43dF17913", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": 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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "_decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "Liquidator": { + "address": "0x40FB27A83e52E7B213CC345f5b6ACA17bf7D5139", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address payable", + "name": "vBnb_", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "address", + "name": "vaiController_", + "type": "address" + }, + { + "internalType": "address", + "name": "treasury_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "treasuryPercentMantissa_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokensForTreasury", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokensForLiquidator", + "type": "uint256" + } + ], + "name": "LiquidateBorrowedTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPercent", + "type": "uint256" + } + ], + "name": "NewLiquidationTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_notEntered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VToken", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newTreasuryPercentMantissa", + "type": "uint256" + } + ], + "name": "setTreasuryPercent", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasury", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercentMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vBnb", + "outputs": [ + { + "internalType": "contract VBNB", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "PegStability_USDT": { + "address": "0xB21E69eef4Bc1D64903fa28D9b32491B1c0786F1", + "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": "AlreadyPaused", + "type": "error" + }, + { + "inputs": [], + "name": "AmountTooSmall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFee", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughVAI", + "type": "error" + }, + { + "inputs": [], + "name": "NotPaused", + "type": "error" + }, + { + "inputs": [], + "name": "Paused", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyDecimals", + "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": "VAIMintCapReached", + "type": "error" + }, + { + "inputs": [], + "name": "VAIMintedUnderflow", + "type": "error" + }, + { + "inputs": [], + "name": "VAITransferFail", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAmount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldFeeIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newFeeIn", + "type": "uint256" + } + ], + "name": "FeeInChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldFeeOut", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newFeeOut", + "type": "uint256" + } + ], + "name": "FeeOutChanged", + "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": "oldOracle", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOracle", + "type": "address" + } + ], + "name": "OracleChanged", + "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": "admin", + "type": "address" + } + ], + "name": "PSMPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PSMResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "stableIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vaiOut", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "StableForVAISwapped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "vaiBurnt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stableOut", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vaiFee", + "type": "uint256" + } + ], + "name": "VAIForStableSwapped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldCap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCap", + "type": "uint256" + } + ], + "name": "VAIMintCapChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldTreasury", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newTreasury", + "type": "address" + } + ], + "name": "VenusTreasuryChanged", + "type": "event" + }, + { + "inputs": [], + "name": "BASIS_POINTS_DIVISOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MANTISSA_ONE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ONE_DOLLAR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STABLE_TOKEN_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VAI", + "outputs": [ + { + "internalType": "contract IVAI", + "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": [], + "name": "feeIn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "internalType": "address", + "name": "venusTreasury_", + "type": "address" + }, + { + "internalType": "address", + "name": "oracleAddress_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "feeIn_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeOut_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaiMintCap_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stableTknAmount", + "type": "uint256" + } + ], + "name": "previewSwapStableForVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stableTknAmount", + "type": "uint256" + } + ], + "name": "previewSwapVAIForStable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeIn_", + "type": "uint256" + } + ], + "name": "setFeeIn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeOut_", + "type": "uint256" + } + ], + "name": "setFeeOut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "oracleAddress_", + "type": "address" + } + ], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaiMintCap_", + "type": "uint256" + } + ], + "name": "setVAIMintCap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "venusTreasury_", + "type": "address" + } + ], + "name": "setVenusTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "stableTknAmount", + "type": "uint256" + } + ], + "name": "swapStableForVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "stableTknAmount", + "type": "uint256" + } + ], + "name": "swapVAIForStable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaiMintCap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusTreasury", + "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" + } + ] + }, + "PegStability_USDT_Implementation": { + "address": "0xDDa903294fB71141302aD3Bf2AF37dD6Cbd5DBbF", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "stableTokenAddress_", + "type": "address" + }, + { + "internalType": "address", + "name": "vaiAddress_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyPaused", + "type": "error" + }, + { + "inputs": [], + "name": "AmountTooSmall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFee", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughVAI", + "type": "error" + }, + { + "inputs": [], + "name": "NotPaused", + "type": "error" + }, + { + "inputs": [], + "name": "Paused", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyDecimals", + "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": "VAIMintCapReached", + "type": "error" + }, + { + "inputs": [], + "name": "VAIMintedUnderflow", + "type": "error" + }, + { + "inputs": [], + "name": "VAITransferFail", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAmount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldFeeIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newFeeIn", + "type": "uint256" + } + ], + "name": "FeeInChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldFeeOut", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newFeeOut", + "type": "uint256" + } + ], + "name": "FeeOutChanged", + "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": "oldOracle", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOracle", + "type": "address" + } + ], + "name": "OracleChanged", + "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": "admin", + "type": "address" + } + ], + "name": "PSMPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PSMResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "stableIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vaiOut", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "StableForVAISwapped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "vaiBurnt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stableOut", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vaiFee", + "type": "uint256" + } + ], + "name": "VAIForStableSwapped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldCap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCap", + "type": "uint256" + } + ], + "name": "VAIMintCapChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldTreasury", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newTreasury", + "type": "address" + } + ], + "name": "VenusTreasuryChanged", + "type": "event" + }, + { + "inputs": [], + "name": "BASIS_POINTS_DIVISOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MANTISSA_ONE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ONE_DOLLAR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STABLE_TOKEN_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VAI", + "outputs": [ + { + "internalType": "contract IVAI", + "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": [], + "name": "feeIn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeOut", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "internalType": "address", + "name": "venusTreasury_", + "type": "address" + }, + { + "internalType": "address", + "name": "oracleAddress_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "feeIn_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeOut_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vaiMintCap_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stableTknAmount", + "type": "uint256" + } + ], + "name": "previewSwapStableForVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "stableTknAmount", + "type": "uint256" + } + ], + "name": "previewSwapVAIForStable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeIn_", + "type": "uint256" + } + ], + "name": "setFeeIn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeOut_", + "type": "uint256" + } + ], + "name": "setFeeOut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "oracleAddress_", + "type": "address" + } + ], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaiMintCap_", + "type": "uint256" + } + ], + "name": "setVAIMintCap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "venusTreasury_", + "type": "address" + } + ], + "name": "setVenusTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "stableTknAmount", + "type": "uint256" + } + ], + "name": "swapStableForVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "stableTknAmount", + "type": "uint256" + } + ], + "name": "swapVAIForStable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaiMintCap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusTreasury", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "PegStability_USDT_Proxy": { + "address": "0xB21E69eef4Bc1D64903fa28D9b32491B1c0786F1", + "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" + } + ] + }, + "PolicyFacet": { + "address": "0x3ff314568008f6aEF7a261e33250c0140299E35C", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributedVAIVaultVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "VenusBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "VenusSupplySpeedUpdated", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "_setVenusSpeeds", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum ComptrollerV9Storage.Action", + "name": "action", + "type": "uint8" + } + ], + "name": "actionPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvedDelegates", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenModify", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "getHypotheticalAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getXVSAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualMintAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract PriceOracle", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "Prime": { + "address": "0xe840F8EC2Dc50E7D22e5e2991975b9F6e34b62Ad", + "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": [ + { + "internalType": "address", + "name": "_wbnb", + "type": "address" + }, + { + "internalType": "address", + "name": "_vbnb", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_blocksPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_stakingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minimumStakedXVS", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maximumXVSCap", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AssetAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "x", + "type": "int256" + } + ], + "name": "ExpTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "IneligibleToClaim", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAlphaArguments", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBlocksPerYear", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFixedPoint", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "d", + "type": "uint256" + } + ], + "name": "InvalidFraction", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLimit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTimestamp", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidVToken", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "x", + "type": "int256" + } + ], + "name": "LnNonRealResult", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "x", + "type": "int256" + } + ], + "name": "LnTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "MarketAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "MarketNotSupported", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "NoScoreUpdatesRequired", + "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": "UserHasNoPrimeToken", + "type": "error" + }, + { + "inputs": [], + "name": "WaitMoreTime", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint128", + "name": "oldNumerator", + "type": "uint128" + }, + { + "indexed": true, + "internalType": "uint128", + "name": "oldDenominator", + "type": "uint128" + }, + { + "indexed": true, + "internalType": "uint128", + "name": "newNumerator", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "newDenominator", + "type": "uint128" + } + ], + "name": "AlphaUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "InterestClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "supplyMultiplier", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "borrowMultiplier", + "type": "uint256" + } + ], + "name": "MarketAdded", + "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": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isIrrevocable", + "type": "bool" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldIrrevocableLimit", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldRevocableLimit", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newIrrevocableLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRevocableLimit", + "type": "uint256" + } + ], + "name": "MintLimitsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldSupplyMultiplier", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldBorrowMultiplier", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSupplyMultiplier", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBorrowMultiplier", + "type": "uint256" + } + ], + "name": "MultiplierUpdated", + "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": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "StakedAtUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "TokenUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "UserScoreUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKS_PER_YEAR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAXIMUM_XVS_CAP", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINIMUM_STAKED_XVS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "accrueInterest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "accrueInterestAndUpdateScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplyMultiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowMultiplier", + "type": "uint256" + } + ], + "name": "addMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "alphaDenominator", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alphaNumerator", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "calculateAPR", + "outputs": [ + { + "internalType": "uint256", + "name": "supplyAPR", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAPR", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "claimInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "claimInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "claimTimeRemaining", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrow", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "xvsStaked", + "type": "uint256" + } + ], + "name": "estimateAPR", + "outputs": [ + { + "internalType": "uint256", + "name": "supplyAPR", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAPR", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllMarkets", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getInterestAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getPendingRewards", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct PrimeStorageV1.PendingReward[]", + "name": "pendingRewards", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "xvsVault_", + "type": "address" + }, + { + "internalType": "address", + "name": "xvsVaultRewardToken_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "xvsVaultPoolId_", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "alphaNumerator_", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "alphaDenominator_", + "type": "uint128" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "internalType": "address", + "name": "primeLiquidityProvider_", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "address", + "name": "oracle_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "interests", + "outputs": [ + { + "internalType": "uint256", + "name": "accrued", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardIndex", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "irrevocableLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isScoreUpdated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "isIrrevocable", + "type": "bool" + }, + { + "internalType": "address[]", + "name": "users", + "type": "address[]" + } + ], + "name": "issue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "uint256", + "name": "supplyMultiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowMultiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sumOfMembersScore", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "exists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextScoreUpdateRoundId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingScoreUpdates", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "primeLiquidityProvider", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocableLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_irrevocableLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_revocableLimit", + "type": "uint256" + } + ], + "name": "setLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "users", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "timestamps", + "type": "uint256[]" + } + ], + "name": "setStakedAt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "stakedAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "togglePause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokens", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isIrrevocable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalIrrevocable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalRevocable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalScoreUpdatesRequired", + "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": "", + "type": "address" + } + ], + "name": "unreleasedPLPIncome", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "_alphaNumerator", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "_alphaDenominator", + "type": "uint128" + } + ], + "name": "updateAlpha", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplyMultiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowMultiplier", + "type": "uint256" + } + ], + "name": "updateMultipliers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "users", + "type": "address[]" + } + ], + "name": "updateScores", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "vTokenForAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "xvsUpdated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "xvsVault", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "xvsVaultPoolId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "xvsVaultRewardToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "PrimeLiquidityProvider": { + "address": "0xAdeddc73eAFCbed174e6C400165b111b0cb80B7E", + "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": "AddressesMustDiffer", + "type": "error" + }, + { + "inputs": [], + "name": "FundsTransferIsPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidArguments", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCaller", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "speed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSpeed", + "type": "uint256" + } + ], + "name": "InvalidDistributionSpeed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenAlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "TokenNotInitialized", + "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": 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": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldSpeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "MaxTokenDistributionSpeedUpdated", + "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": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPrimeToken", + "type": "address" + } + ], + "name": "PrimeTokenUpdated", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenDistributionInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldSpeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "TokenDistributionSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenTransferredToPrime", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensAccrued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_DISTRIBUTION_SPEED", + "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": "token_", + "type": "address" + } + ], + "name": "accrueTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "getEffectiveDistributionSpeed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "distributionSpeeds_", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "maxDistributionSpeeds_", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + } + ], + "name": "initializeTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastAccruedBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "maxTokenDistributionSpeeds", + "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": "pauseFundsTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resumeFundsTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "maxDistributionSpeeds_", + "type": "uint256[]" + } + ], + "name": "setMaxTokensDistributionSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prime_", + "type": "address" + } + ], + "name": "setPrimeToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "distributionSpeeds_", + "type": "uint256[]" + } + ], + "name": "setTokensDistributionSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token_", + "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": "", + "type": "address" + } + ], + "name": "tokenAmountAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenDistributionSpeeds", + "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": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "PrimeLiquidityProviderTest": { + "address": "0x7a780FbBa026568025a82101De65863A94CcD8f7", + "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": "AddressesMustDiffer", + "type": "error" + }, + { + "inputs": [], + "name": "FundsTransferIsPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidArguments", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCaller", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "speed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSpeed", + "type": "uint256" + } + ], + "name": "InvalidDistributionSpeed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenAlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "TokenNotInitialized", + "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": 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": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldSpeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "MaxTokenDistributionSpeedUpdated", + "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": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPrimeToken", + "type": "address" + } + ], + "name": "PrimeTokenUpdated", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenDistributionInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldSpeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "TokenDistributionSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenTransferredToPrime", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensAccrued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_DISTRIBUTION_SPEED", + "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": "token_", + "type": "address" + } + ], + "name": "accrueTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "getEffectiveDistributionSpeed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "distributionSpeeds_", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "maxDistributionSpeeds_", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + } + ], + "name": "initializeTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastAccruedBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "maxTokenDistributionSpeeds", + "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": "pauseFundsTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resumeFundsTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "maxDistributionSpeeds_", + "type": "uint256[]" + } + ], + "name": "setMaxTokensDistributionSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prime_", + "type": "address" + } + ], + "name": "setPrimeToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "distributionSpeeds_", + "type": "uint256[]" + } + ], + "name": "setTokensDistributionSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token_", + "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": "", + "type": "address" + } + ], + "name": "tokenAmountAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenDistributionSpeeds", + "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": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "PrimeLiquidityProviderTest_Implementation": { + "address": "0x9Ac449Fe41e67E5161C01d9366f655a8A7406A76", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AddressesMustDiffer", + "type": "error" + }, + { + "inputs": [], + "name": "FundsTransferIsPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidArguments", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCaller", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "speed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSpeed", + "type": "uint256" + } + ], + "name": "InvalidDistributionSpeed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenAlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "TokenNotInitialized", + "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": 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": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldSpeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "MaxTokenDistributionSpeedUpdated", + "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": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPrimeToken", + "type": "address" + } + ], + "name": "PrimeTokenUpdated", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenDistributionInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldSpeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "TokenDistributionSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenTransferredToPrime", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensAccrued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_DISTRIBUTION_SPEED", + "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": "token_", + "type": "address" + } + ], + "name": "accrueTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "getEffectiveDistributionSpeed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "distributionSpeeds_", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "maxDistributionSpeeds_", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + } + ], + "name": "initializeTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastAccruedBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "maxTokenDistributionSpeeds", + "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": "pauseFundsTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resumeFundsTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "maxDistributionSpeeds_", + "type": "uint256[]" + } + ], + "name": "setMaxTokensDistributionSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prime_", + "type": "address" + } + ], + "name": "setPrimeToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "distributionSpeeds_", + "type": "uint256[]" + } + ], + "name": "setTokensDistributionSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token_", + "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": "", + "type": "address" + } + ], + "name": "tokenAmountAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenDistributionSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "PrimeLiquidityProviderTest_Proxy": { + "address": "0x7a780FbBa026568025a82101De65863A94CcD8f7", + "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" + } + ] + }, + "PrimeLiquidityProvider_Implementation": { + "address": "0x98d73B2E246a3506686CBA62d2118D2127dfD20E", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AddressesMustDiffer", + "type": "error" + }, + { + "inputs": [], + "name": "FundsTransferIsPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidArguments", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCaller", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "speed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSpeed", + "type": "uint256" + } + ], + "name": "InvalidDistributionSpeed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenAlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "TokenNotInitialized", + "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": 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": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldSpeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "MaxTokenDistributionSpeedUpdated", + "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": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPrimeToken", + "type": "address" + } + ], + "name": "PrimeTokenUpdated", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenDistributionInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldSpeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "TokenDistributionSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenTransferredToPrime", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensAccrued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_DISTRIBUTION_SPEED", + "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": "token_", + "type": "address" + } + ], + "name": "accrueTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "getEffectiveDistributionSpeed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "distributionSpeeds_", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "maxDistributionSpeeds_", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + } + ], + "name": "initializeTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastAccruedBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "maxTokenDistributionSpeeds", + "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": "pauseFundsTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token_", + "type": "address" + } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resumeFundsTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "maxDistributionSpeeds_", + "type": "uint256[]" + } + ], + "name": "setMaxTokensDistributionSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prime_", + "type": "address" + } + ], + "name": "setPrimeToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens_", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "distributionSpeeds_", + "type": "uint256[]" + } + ], + "name": "setTokensDistributionSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token_", + "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": "", + "type": "address" + } + ], + "name": "tokenAmountAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenDistributionSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "PrimeLiquidityProvider_Proxy": { + "address": "0xAdeddc73eAFCbed174e6C400165b111b0cb80B7E", + "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" + } + ] + }, + "Prime_Implementation": { + "address": "0x72C9Bc4433C912ecd8184B3F7dda55Ee25761896", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_wbnb", + "type": "address" + }, + { + "internalType": "address", + "name": "_vbnb", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_blocksPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_stakingPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minimumStakedXVS", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maximumXVSCap", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AssetAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "x", + "type": "int256" + } + ], + "name": "ExpTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "IneligibleToClaim", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAlphaArguments", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBlocksPerYear", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFixedPoint", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "d", + "type": "uint256" + } + ], + "name": "InvalidFraction", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLimit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTimestamp", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidVToken", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "x", + "type": "int256" + } + ], + "name": "LnNonRealResult", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "x", + "type": "int256" + } + ], + "name": "LnTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "MarketAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "MarketNotSupported", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "NoScoreUpdatesRequired", + "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": "UserHasNoPrimeToken", + "type": "error" + }, + { + "inputs": [], + "name": "WaitMoreTime", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint128", + "name": "oldNumerator", + "type": "uint128" + }, + { + "indexed": true, + "internalType": "uint128", + "name": "oldDenominator", + "type": "uint128" + }, + { + "indexed": true, + "internalType": "uint128", + "name": "newNumerator", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "newDenominator", + "type": "uint128" + } + ], + "name": "AlphaUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "InterestClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "supplyMultiplier", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "borrowMultiplier", + "type": "uint256" + } + ], + "name": "MarketAdded", + "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": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isIrrevocable", + "type": "bool" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldIrrevocableLimit", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldRevocableLimit", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newIrrevocableLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRevocableLimit", + "type": "uint256" + } + ], + "name": "MintLimitsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldSupplyMultiplier", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldBorrowMultiplier", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSupplyMultiplier", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBorrowMultiplier", + "type": "uint256" + } + ], + "name": "MultiplierUpdated", + "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": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "StakedAtUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "TokenUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "UserScoreUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKS_PER_YEAR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAXIMUM_XVS_CAP", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINIMUM_STAKED_XVS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "accrueInterest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "accrueInterestAndUpdateScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplyMultiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowMultiplier", + "type": "uint256" + } + ], + "name": "addMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "alphaDenominator", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alphaNumerator", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "calculateAPR", + "outputs": [ + { + "internalType": "uint256", + "name": "supplyAPR", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAPR", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "claimInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "claimInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "claimTimeRemaining", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrow", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "xvsStaked", + "type": "uint256" + } + ], + "name": "estimateAPR", + "outputs": [ + { + "internalType": "uint256", + "name": "supplyAPR", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAPR", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllMarkets", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getInterestAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getPendingRewards", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct PrimeStorageV1.PendingReward[]", + "name": "pendingRewards", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "xvsVault_", + "type": "address" + }, + { + "internalType": "address", + "name": "xvsVaultRewardToken_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "xvsVaultPoolId_", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "alphaNumerator_", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "alphaDenominator_", + "type": "uint128" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "internalType": "address", + "name": "primeLiquidityProvider_", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "address", + "name": "oracle_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "interests", + "outputs": [ + { + "internalType": "uint256", + "name": "accrued", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardIndex", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "irrevocableLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isScoreUpdated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "isIrrevocable", + "type": "bool" + }, + { + "internalType": "address[]", + "name": "users", + "type": "address[]" + } + ], + "name": "issue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "uint256", + "name": "supplyMultiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowMultiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sumOfMembersScore", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "exists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextScoreUpdateRoundId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingScoreUpdates", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "primeLiquidityProvider", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocableLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_irrevocableLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_revocableLimit", + "type": "uint256" + } + ], + "name": "setLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "users", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "timestamps", + "type": "uint256[]" + } + ], + "name": "setStakedAt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "stakedAt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "togglePause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokens", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isIrrevocable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalIrrevocable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalRevocable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalScoreUpdatesRequired", + "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": "", + "type": "address" + } + ], + "name": "unreleasedPLPIncome", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "_alphaNumerator", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "_alphaDenominator", + "type": "uint128" + } + ], + "name": "updateAlpha", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplyMultiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowMultiplier", + "type": "uint256" + } + ], + "name": "updateMultipliers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "users", + "type": "address[]" + } + ], + "name": "updateScores", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "vTokenForAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "xvsUpdated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "xvsVault", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "xvsVaultPoolId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "xvsVaultRewardToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "Prime_Proxy": { + "address": "0xe840F8EC2Dc50E7D22e5e2991975b9F6e34b62Ad", + "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" + } + ] + }, + "SXP": { + "address": "0x75107940Cf1121232C0559c747A986DEfbc69DA9", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initialAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_tokenName", + "type": "string" + }, + { + "internalType": "uint8", + "name": "_decimalUnits", + "type": "uint8" + }, + { + "internalType": "string", + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "SetterFacet": { + "address": "0x3e7F29179A1b6fB43d9fecc1e23e675B1F740634", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "enum ComptrollerV9Storage.Action", + "name": "action", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "pauseState", + "type": "bool" + } + ], + "name": "ActionPausedMarket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "ActionProtocolPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributedVAIVaultVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "IsForcedLiquidationEnabledUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControl", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBorrowCap", + "type": "uint256" + } + ], + "name": "NewBorrowCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldComptrollerLens", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newComptrollerLens", + "type": "address" + } + ], + "name": "NewComptrollerLens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldLiquidatorContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newLiquidatorContract", + "type": "address" + } + ], + "name": "NewLiquidatorContract", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract PriceOracle", + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract PriceOracle", + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IPrime", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IPrime", + "name": "newPrimeToken", + "type": "address" + } + ], + "name": "NewPrimeToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSupplyCap", + "type": "uint256" + } + ], + "name": "NewSupplyCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + } + ], + "name": "NewTreasuryAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + } + ], + "name": "NewTreasuryGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTreasuryPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "NewTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "oldVAIController", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "newVAIController", + "type": "address" + } + ], + "name": "NewVAIController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVAIMintRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "NewVAIMintRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseInterval_", + "type": "uint256" + } + ], + "name": "NewVAIVaultInfo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVenusVAIVaultRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVenusVAIVaultRate", + "type": "uint256" + } + ], + "name": "NewVenusVAIVaultRate", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "_setAccessControl", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address[]", + "name": "markets_", + "type": "address[]" + }, + { + "internalType": "enum ComptrollerV9Storage.Action[]", + "name": "actions_", + "type": "uint8[]" + }, + { + "internalType": "bool", + "name": "paused_", + "type": "bool" + } + ], + "name": "_setActionsPaused", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "comptrollerLens_", + "type": "address" + } + ], + "name": "_setComptrollerLens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "_setForcedLiquidation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newLiquidatorContract_", + "type": "address" + } + ], + "name": "_setLiquidatorContract", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "_setMarketBorrowCaps", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "_setMarketSupplyCaps", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "_setPauseGuardian", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract PriceOracle", + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_prime", + "type": "address" + } + ], + "name": "_setPrimeToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "_setProtocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + }, + { + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "_setTreasuryData", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "vaiController_", + "type": "address" + } + ], + "name": "_setVAIController", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "_setVAIMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minReleaseAmount_", + "type": "uint256" + } + ], + "name": "_setVAIVaultInfo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "venusVAIVaultRate_", + "type": "uint256" + } + ], + "name": "_setVenusVAIVaultRate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum ComptrollerV9Storage.Action", + "name": "action", + "type": "uint8" + } + ], + "name": "actionPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvedDelegates", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getXVSAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract PriceOracle", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setMintedVAIOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "SnapshotLens": { + "address": "0x61610DeC84448Ed17A2a0317667a99ca0CC6f697", + "abi": [ + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "comptrollerAddress", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "assetName", + "type": "string" + }, + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyInUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateral", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowsInUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "assetPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accruedInterest", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isACollateral", + "type": "bool" + } + ], + "internalType": "struct SnapshotLens.AccountSnapshot[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "comptrollerAddress", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "assetName", + "type": "string" + }, + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyInUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "collateral", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowsInUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "assetPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accruedInterest", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isACollateral", + "type": "bool" + } + ], + "internalType": "struct SnapshotLens.AccountSnapshot", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "comptrollerAddress", + "type": "address" + } + ], + "name": "isACollateral", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "SwapRouterCorePool": { + "address": "0x83edf1deE1B730b7e8e13C00ba76027D63a51ac0", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "WBNB_", + "type": "address" + }, + { + "internalType": "address", + "name": "factory_", + "type": "address" + }, + { + "internalType": "address", + "name": "_comptrollerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountMax", + "type": "uint256" + } + ], + "name": "ExcessiveInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountIntMax", + "type": "uint256" + } + ], + "name": "InputAmountAboveMaximum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientOutputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPath", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "OutputAmountBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCheck", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RepayError", + "type": "error" + }, + { + "inputs": [], + "name": "SafeApproveFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferBNBFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFromFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "SupplyError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestemp", + "type": "uint256" + } + ], + "name": "SwapDeadlineExpire", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying", + "type": "address" + } + ], + "name": "VTokenUnderlyingInvalid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "expectedAdddress", + "type": "address" + }, + { + "internalType": "address", + "name": "passedAddress", + "type": "address" + } + ], + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "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": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapBnbForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapBnbForTokensAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForBnb", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForBnbAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForTokensAtSupportingFee", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "VBNBAddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountIn", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "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": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "name": "quote", + "outputs": [ + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "name": "setVBNBAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullBNBDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNBAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "SwapRouterDefi": { + "address": "0x76B88ff4579B35D2722B7383b9B9ce831dc89B72", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "WBNB_", + "type": "address" + }, + { + "internalType": "address", + "name": "factory_", + "type": "address" + }, + { + "internalType": "address", + "name": "_comptrollerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountMax", + "type": "uint256" + } + ], + "name": "ExcessiveInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountIntMax", + "type": "uint256" + } + ], + "name": "InputAmountAboveMaximum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientOutputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPath", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "OutputAmountBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCheck", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RepayError", + "type": "error" + }, + { + "inputs": [], + "name": "SafeApproveFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferBNBFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFromFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "SupplyError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestemp", + "type": "uint256" + } + ], + "name": "SwapDeadlineExpire", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying", + "type": "address" + } + ], + "name": "VTokenUnderlyingInvalid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "expectedAdddress", + "type": "address" + }, + { + "internalType": "address", + "name": "passedAddress", + "type": "address" + } + ], + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "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": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapBnbForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapBnbForTokensAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForBnb", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForBnbAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForTokensAtSupportingFee", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "VBNBAddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountIn", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "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": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "name": "quote", + "outputs": [ + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "name": "setVBNBAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullBNBDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNBAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "SwapRouterGamefi": { + "address": "0xFdeBF4530F9c7d352ffFE88cd0e96C8Bb7391BD9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "WBNB_", + "type": "address" + }, + { + "internalType": "address", + "name": "factory_", + "type": "address" + }, + { + "internalType": "address", + "name": "_comptrollerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountMax", + "type": "uint256" + } + ], + "name": "ExcessiveInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountIntMax", + "type": "uint256" + } + ], + "name": "InputAmountAboveMaximum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientOutputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPath", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "OutputAmountBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCheck", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RepayError", + "type": "error" + }, + { + "inputs": [], + "name": "SafeApproveFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferBNBFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFromFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "SupplyError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestemp", + "type": "uint256" + } + ], + "name": "SwapDeadlineExpire", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying", + "type": "address" + } + ], + "name": "VTokenUnderlyingInvalid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "expectedAdddress", + "type": "address" + }, + { + "internalType": "address", + "name": "passedAddress", + "type": "address" + } + ], + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "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": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapBnbForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapBnbForTokensAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForBnb", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForBnbAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForTokensAtSupportingFee", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "VBNBAddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountIn", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "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": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "name": "quote", + "outputs": [ + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "name": "setVBNBAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullBNBDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNBAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "SwapRouterLiquidStakedBNB": { + "address": "0x7DcBd10E3479907e0B8C79d01D0572C8cc00227B", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "WBNB_", + "type": "address" + }, + { + "internalType": "address", + "name": "factory_", + "type": "address" + }, + { + "internalType": "address", + "name": "_comptrollerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountMax", + "type": "uint256" + } + ], + "name": "ExcessiveInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountIntMax", + "type": "uint256" + } + ], + "name": "InputAmountAboveMaximum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientOutputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPath", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "OutputAmountBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCheck", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RepayError", + "type": "error" + }, + { + "inputs": [], + "name": "SafeApproveFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferBNBFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFromFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "SupplyError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestemp", + "type": "uint256" + } + ], + "name": "SwapDeadlineExpire", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying", + "type": "address" + } + ], + "name": "VTokenUnderlyingInvalid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "expectedAdddress", + "type": "address" + }, + { + "internalType": "address", + "name": "passedAddress", + "type": "address" + } + ], + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "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": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapBnbForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapBnbForTokensAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForBnb", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForBnbAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForTokensAtSupportingFee", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "VBNBAddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountIn", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "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": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "name": "quote", + "outputs": [ + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "name": "setVBNBAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullBNBDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNBAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "SwapRouterStableCoins": { + "address": "0x6cE131c2321e25d7b4C63283b75DB160Ce3Fb710", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "WBNB_", + "type": "address" + }, + { + "internalType": "address", + "name": "factory_", + "type": "address" + }, + { + "internalType": "address", + "name": "_comptrollerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountMax", + "type": "uint256" + } + ], + "name": "ExcessiveInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountIntMax", + "type": "uint256" + } + ], + "name": "InputAmountAboveMaximum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientOutputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPath", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "OutputAmountBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCheck", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RepayError", + "type": "error" + }, + { + "inputs": [], + "name": "SafeApproveFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferBNBFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFromFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "SupplyError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestemp", + "type": "uint256" + } + ], + "name": "SwapDeadlineExpire", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying", + "type": "address" + } + ], + "name": "VTokenUnderlyingInvalid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "expectedAdddress", + "type": "address" + }, + { + "internalType": "address", + "name": "passedAddress", + "type": "address" + } + ], + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "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": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapBnbForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapBnbForTokensAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForBnb", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForBnbAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForTokensAtSupportingFee", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "VBNBAddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountIn", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "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": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "name": "quote", + "outputs": [ + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "name": "setVBNBAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullBNBDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNBAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "SwapRouterTronFamily": { + "address": "0x51Fd03aD1132e8cb5a5a793528c9F4ec918667d4", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "WBNB_", + "type": "address" + }, + { + "internalType": "address", + "name": "factory_", + "type": "address" + }, + { + "internalType": "address", + "name": "_comptrollerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountMax", + "type": "uint256" + } + ], + "name": "ExcessiveInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountIntMax", + "type": "uint256" + } + ], + "name": "InputAmountAboveMaximum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientInputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientOutputAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPath", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "OutputAmountBelowMinimum", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCheck", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "repayer", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RepayError", + "type": "error" + }, + { + "inputs": [], + "name": "SafeApproveFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferBNBFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFromFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "SupplyError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + } + ], + "name": "SwapAmountLessThanAmountOutMin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestemp", + "type": "uint256" + } + ], + "name": "SwapDeadlineExpire", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "VTokenNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying", + "type": "address" + } + ], + "name": "VTokenUnderlyingInvalid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "expectedAdddress", + "type": "address" + }, + { + "internalType": "address", + "name": "passedAddress", + "type": "address" + } + ], + "name": "WrongAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "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": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapBnbForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapBnbForTokensAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForBnb", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForBnbAtSupportingFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "indexed": true, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "SwapTokensForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "swapper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "SwapTokensForTokensAtSupportingFee", + "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": "sweepAmount", + "type": "uint256" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "VBNBAddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountIn", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + } + ], + "name": "getAmountsOut", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "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": "uint256", + "name": "amountA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveA", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveB", + "type": "uint256" + } + ], + "name": "quote", + "outputs": [ + { + "internalType": "uint256", + "name": "amountB", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vBNBAddress", + "type": "address" + } + ], + "name": "setVBNBAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForExactTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapBNBForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupply", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactBNBForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForBNBAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndRepayAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAndSupplyAtSupportingFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapExactTokensForTokensAtSupportingFee", + "outputs": [ + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNB", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactBNBAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForExactTokensAndSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullBNBDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountInMax", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "path", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapTokensForFullTokenDebtAndRepay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sweepAmount", + "type": "uint256" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNBAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "TUSD": { + "address": "0xB32171ecD878607FFc4F8FC0bCcE6852BB3149E0", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initialAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_tokenName", + "type": "string" + }, + { + "internalType": "uint8", + "name": "_decimalUnits", + "type": "uint8" + }, + { + "internalType": "string", + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "USDC": { + "address": "0x16227D60f7a0e586C66B005219dfc887D13C9531", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initialAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_tokenName", + "type": "string" + }, + { + "internalType": "uint8", + "name": "_decimalUnits", + "type": "uint8" + }, + { + "internalType": "string", + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "USDT": { + "address": "0xA11c8D9DC9b66E209Ef60F0C8D969D3CD988782c", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initialAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_tokenName", + "type": "string" + }, + { + "internalType": "uint8", + "name": "_decimalUnits", + "type": "uint8" + }, + { + "internalType": "string", + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "Unitroller": { + "address": "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + } + ], + "name": "DiamondCut", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract Unitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvedDelegates", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "diamondCut_", + "type": "tuple[]" + } + ], + "name": "diamondCut", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes4", + "name": "functionSelector", + "type": "bytes4" + } + ], + "name": "facetAddress", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "uint96", + "name": "functionSelectorPosition", + "type": "uint96" + } + ], + "internalType": "struct ComptrollerV13Storage.FacetAddressAndPosition", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "facetAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetFunctionSelectors", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "", + "type": "bytes4[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetPosition", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "facets", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct Diamond.Facet[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract PriceOracle", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "Unitroller_Implementation": { + "address": "0x7e0298880224b8116f3462c50917249e94b3dc53", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + } + ], + "name": "DiamondCut", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract Unitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvedDelegates", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "diamondCut_", + "type": "tuple[]" + } + ], + "name": "diamondCut", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes4", + "name": "functionSelector", + "type": "bytes4" + } + ], + "name": "facetAddress", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "uint96", + "name": "functionSelectorPosition", + "type": "uint96" + } + ], + "internalType": "struct ComptrollerV13Storage.FacetAddressAndPosition", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "facetAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetFunctionSelectors", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "", + "type": "bytes4[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetPosition", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "facets", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct Diamond.Facet[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract PriceOracle", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "Unitroller_Proxy": { + "address": "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VAI": { + "address": "0x5fFbE5302BadED40941A403228E6AD03f93752d9", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainId_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": true, + "inputs": [ + { + "indexed": true, + "internalType": "bytes4", + "name": "sig", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "usr", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "arg1", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "arg2", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "LogNote", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "usr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "usr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "guy", + "type": "address" + } + ], + "name": "deny", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "usr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "move", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "usr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "pull", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "usr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "push", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "guy", + "type": "address" + } + ], + "name": "rely", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "wards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VAIVault": { + "address": "0x5c1c23ac038059c7B4EC1659728c166facab590b", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "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": "admin", + "type": "address" + } + ], + "name": "VaultPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IVAIVaultProxy", + "name": "vaiVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accXVSPerShare", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV5", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingXVS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "resume", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvs", + "type": "address" + }, + { + "internalType": "address", + "name": "_vai", + "type": "address" + } + ], + "name": "setVenusInfo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "updatePendingRewards", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardDebt", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vai", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvs", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VAIVaultProxy": { + "address": "0x7Db4f5cC3bBA3e12FF1F528D2e3417afb0a57118", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminTransfered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VAIVaultProxy", + "name": "vaiVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accXVSPerShare", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "burnAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingXVS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "setNewAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvs", + "type": "address" + }, + { + "internalType": "address", + "name": "_vai", + "type": "address" + } + ], + "name": "setVenusInfo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "updatePendingRewards", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardDebt", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vai", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvs", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VAIVaultProxy_Implementation": { + "address": "0x3f047c3022b35ed59484a4ee12b28849903a8c3b", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminTransfered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VAIVaultProxy", + "name": "vaiVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accXVSPerShare", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "burnAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingXVS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "setNewAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvs", + "type": "address" + }, + { + "internalType": "address", + "name": "_vai", + "type": "address" + } + ], + "name": "setVenusInfo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "updatePendingRewards", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardDebt", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vai", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvs", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VAIVaultProxy_Proxy": { + "address": "0x7Db4f5cC3bBA3e12FF1F528D2e3417afb0a57118", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VBNBAdmin": { + "address": "0x04109575c1dbB4ac2e59e60c783800ea10441BBe", + "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": [ + { + "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": 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": "contract IProtocolShareReserve", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IProtocolShareReserve", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "ProtocolShareReserveUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "contract IWBNB", + "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": "contract IProtocolShareReserve", + "name": "_protocolShareReserve", + "type": "address" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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": "protocolShareReserve", + "outputs": [ + { + "internalType": "contract IProtocolShareReserve", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "reduceReserves", + "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": "contract IProtocolShareReserve", + "name": "protocolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "contract VTokenInterface", + "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" + } + ] + }, + "VBNBAdmin_Implementation": { + "address": "0x698B2c7c82B980265ed4B4a7653a5735E93767b4", + "abi": [ + { + "inputs": [ + { + "internalType": "contract VTokenInterface", + "name": "_vBNB", + "type": "address" + }, + { + "internalType": "contract IWBNB", + "name": "_WBNB", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": 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": "contract IProtocolShareReserve", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IProtocolShareReserve", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "ProtocolShareReserveUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "WBNB", + "outputs": [ + { + "internalType": "contract IWBNB", + "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": "contract IProtocolShareReserve", + "name": "_protocolShareReserve", + "type": "address" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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": "protocolShareReserve", + "outputs": [ + { + "internalType": "contract IProtocolShareReserve", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "reduceReserves", + "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": "contract IProtocolShareReserve", + "name": "protocolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "contract VTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VBNBAdmin_Proxy": { + "address": "0x04109575c1dbB4ac2e59e60c783800ea10441BBe", + "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" + } + ] + }, + "VRT": { + "address": "0x331F639B4F3CF6E391CD244e0b5027C5968Ec325", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Freezed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "UnFreezed", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rawAmount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "fromBlock", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "freeze", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getCurrentVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getPriorVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rawAmount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rawAmount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "unfreeze", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VRTConverter": { + "address": "0xF0fCB229031A386C672e291cE183390c1a7705dA", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "conversionRatio", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "conversionStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "conversionPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "conversionEndTime", + "type": "uint256" + } + ], + "name": "ConversionInfoSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "reedeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "vrtAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vrtAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "xvsAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "xvsAmount", + "type": "uint256" + } + ], + "name": "TokenConverted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenWithdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "xvsVestingAddress", + "type": "address" + } + ], + "name": "XVSVestingSet", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DEAD_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VRTConverterProxy", + "name": "vrtConverterProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_notEntered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "conversionEndTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "conversionPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "conversionRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "conversionStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "vrtAmount", + "type": "uint256" + } + ], + "name": "convert", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_vrtAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_xvsAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_conversionRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_conversionStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_conversionPeriod", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "initialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isConversionActive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvsVestingAddress", + "type": "address" + } + ], + "name": "setXVSVesting", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalVrtConverted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vrt", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vrtDecimalsMultiplier", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvs", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsDecimalsMultiplier", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsVesting", + "outputs": [ + { + "internalType": "contract IXVSVesting", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VRTConverterProxy": { + "address": "0xAb81e79F9607eC4C7b69Ab4f7cf6c0AF607aA131", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "address", + "name": "_vrtAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_xvsAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_conversionRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_conversionStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_conversionPeriod", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VRTVault": { + "address": "0xa298713eCaE4e2C35C3af5241AAf81E0cc34Da84", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminTransfered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAmount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldLastAccruingBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLastAccruingBlock", + "type": "uint256" + } + ], + "name": "LastAccruingBlockChanged", + "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": "admin", + "type": "address" + } + ], + "name": "VaultPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalPrincipalAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accruedInterest", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawToken", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IVRTVaultProxy", + "name": "vrtVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_notEntered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV5", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "depositAmount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "getAccruedInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_vrtAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_interestRatePerBlock", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lastAccruingBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "resume", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_lastAccruingBlock", + "type": "uint256" + } + ], + "name": "setLastAccruingBlock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userInfo", + "outputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "accrualStartBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalPrincipalAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastWithdrawnBlockNumber", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vrt", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawBep20", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VRTVaultProxy": { + "address": "0x1ffD1b8B67A1AE0C189c734B0F58B0954522FF71", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "address", + "name": "vrtAddress_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "interestRatePerBlock_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAmount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldLastAccruingBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLastAccruingBlock", + "type": "uint256" + } + ], + "name": "LastAccruingBlockChanged", + "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": "admin", + "type": "address" + } + ], + "name": "VaultPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalPrincipalAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accruedInterest", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawToken", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_LAST_ACCRUING_BLOCK", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IVRTVaultProxy", + "name": "vrtVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_notEntered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV5", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "depositAmount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "getAccruedInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_vrtAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_interestRatePerBlock", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lastAccruingBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "resume", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_lastAccruingBlock", + "type": "uint256" + } + ], + "name": "setLastAccruingBlock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userInfo", + "outputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "accrualStartBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalPrincipalAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastWithdrawnBlockNumber", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vrt", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawBep20", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VRTVaultProxy_Implementation": { + "address": "0x06ad3e299dc946fef2afa1f5e251682d52f4ebb6", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAmount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldLastAccruingBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLastAccruingBlock", + "type": "uint256" + } + ], + "name": "LastAccruingBlockChanged", + "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": "admin", + "type": "address" + } + ], + "name": "VaultPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalPrincipalAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accruedInterest", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawToken", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_LAST_ACCRUING_BLOCK", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IVRTVaultProxy", + "name": "vrtVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_notEntered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV5", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "depositAmount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + } + ], + "name": "getAccruedInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_vrtAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_interestRatePerBlock", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lastAccruingBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "resume", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_lastAccruingBlock", + "type": "uint256" + } + ], + "name": "setLastAccruingBlock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userInfo", + "outputs": [ + { + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "accrualStartBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalPrincipalAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastWithdrawnBlockNumber", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vrt", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawBep20", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VRTVaultProxy_Proxy": { + "address": "0x1ffD1b8B67A1AE0C189c734B0F58B0954522FF71", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "address", + "name": "vrtAddress_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "interestRatePerBlock_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VTreasury": { + "address": "0x8b293600c50d6fbdc6ed4251cc75ece29880276f", + "abi": [ + { + "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": false, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "WithdrawTreasuryBEP20", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "WithdrawTreasuryBNB", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawTreasuryBEP20", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawTreasuryBNB", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + } + ] + }, + "VaiController": { + "address": "0x7CE5E45a34104d6Df05779c3d3Fe71c9F11843C5", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateVAI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + } + ], + "name": "MintFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintVAIAmount", + "type": "uint256" + } + ], + "name": "MintVAI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + } + ], + "name": "NewTreasuryAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + } + ], + "name": "NewTreasuryGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTreasuryPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "NewTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayVAIAmount", + "type": "uint256" + } + ], + "name": "RepayVAI", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VAIUnitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + }, + { + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "_setTreasuryData", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "getMintableVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVenusVAIInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintVAIAmount", + "type": "uint256" + } + ], + "name": "mintVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayVAIAmount", + "type": "uint256" + } + ], + "name": "repayVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusVAIMinterIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VaiUnitroller": { + "address": "0xf70C3C6b749BbAb89C081737334E74C9aFD4BE16", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateVAI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + } + ], + "name": "MintFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintVAIAmount", + "type": "uint256" + } + ], + "name": "MintVAI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControl", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + } + ], + "name": "NewTreasuryAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + } + ], + "name": "NewTreasuryGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTreasuryPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "NewTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldBaseRateMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBaseRateMantissa", + "type": "uint256" + } + ], + "name": "NewVAIBaseRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldFloatRateMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newFlatRateMantissa", + "type": "uint256" + } + ], + "name": "NewVAIFloatRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMintCap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMintCap", + "type": "uint256" + } + ], + "name": "NewVAIMintCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldReceiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newReceiver", + "type": "address" + } + ], + "name": "NewVAIReceiver", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayVAIAmount", + "type": "uint256" + } + ], + "name": "RepayVAI", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VAIUnitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + }, + { + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "_setTreasuryData", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControl", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueVAIInterest", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "baseRateMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "floatRateMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "getMintableVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "getVAICalculateRepayAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVAIRepayAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIRepayRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIRepayRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVenusVAIInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintVAIAmount", + "type": "uint256" + } + ], + "name": "mintVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "pastVAIInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "receiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayVAIAmount", + "type": "uint256" + } + ], + "name": "repayVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newBaseRateMantissa", + "type": "uint256" + } + ], + "name": "setBaseRate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newFloatRateMantissa", + "type": "uint256" + } + ], + "name": "setFloatRate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_mintCap", + "type": "uint256" + } + ], + "name": "setMintCap", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newReceiver", + "type": "address" + } + ], + "name": "setReceiver", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusVAIMinterIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VaiUnitroller_Implementation": { + "address": "0xc54fe918b746c1f54609d7f4b1cfee5bb15a5a0f", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateVAI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + } + ], + "name": "MintFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintVAIAmount", + "type": "uint256" + } + ], + "name": "MintVAI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControl", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + } + ], + "name": "NewTreasuryAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + } + ], + "name": "NewTreasuryGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTreasuryPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "NewTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldBaseRateMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBaseRateMantissa", + "type": "uint256" + } + ], + "name": "NewVAIBaseRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldFloatRateMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newFlatRateMantissa", + "type": "uint256" + } + ], + "name": "NewVAIFloatRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMintCap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMintCap", + "type": "uint256" + } + ], + "name": "NewVAIMintCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldReceiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newReceiver", + "type": "address" + } + ], + "name": "NewVAIReceiver", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayVAIAmount", + "type": "uint256" + } + ], + "name": "RepayVAI", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VAIUnitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + }, + { + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "_setTreasuryData", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControl", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueVAIInterest", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "baseRateMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "floatRateMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "getMintableVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "getVAICalculateRepayAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVAIRepayAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIRepayRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIRepayRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVenusVAIInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintVAIAmount", + "type": "uint256" + } + ], + "name": "mintVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "pastVAIInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "receiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayVAIAmount", + "type": "uint256" + } + ], + "name": "repayVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newBaseRateMantissa", + "type": "uint256" + } + ], + "name": "setBaseRate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newFloatRateMantissa", + "type": "uint256" + } + ], + "name": "setFloatRate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_mintCap", + "type": "uint256" + } + ], + "name": "setMintCap", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newReceiver", + "type": "address" + } + ], + "name": "setReceiver", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusVAIMinterIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VaiUnitroller_Proxy": { + "address": "0xf70C3C6b749BbAb89C081737334E74C9aFD4BE16", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "VenusLens": { + "address": "0x11c8dC3DcA87E8205ec01e6d79Be9442d31701d3", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "BLOCKS_PER_DAY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountLimits", + "outputs": [ + { + "components": [ + { + "internalType": "contract VToken[]", + "name": "markets", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.AccountLimits", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "comptrollerAddress", + "type": "address" + } + ], + "name": "getDailyXVS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "contract GovernorAlpha", + "name": "governor", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "proposalIds", + "type": "uint256[]" + } + ], + "name": "getGovProposals", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "eta", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "string[]", + "name": "signatures", + "type": "string[]" + }, + { + "internalType": "bytes[]", + "name": "calldatas", + "type": "bytes[]" + }, + { + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "forVotes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "againstVotes", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "canceled", + "type": "bool" + }, + { + "internalType": "bool", + "name": "executed", + "type": "bool" + } + ], + "internalType": "struct VenusLens.GovProposal[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "contract GovernorAlpha", + "name": "governor", + "type": "address" + }, + { + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "proposalIds", + "type": "uint256[]" + } + ], + "name": "getGovReceipts", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "proposalId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "hasVoted", + "type": "bool" + }, + { + "internalType": "bool", + "name": "support", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "internalType": "struct VenusLens.GovReceipt[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "contract XVS", + "name": "xvs", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint32[]", + "name": "blockNumbers", + "type": "uint32[]" + } + ], + "name": "getVenusVotes", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.VenusVotes[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "contract XVS", + "name": "xvs", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getXVSBalanceMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + } + ], + "internalType": "struct VenusLens.XVSBalanceMetadata", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract XVS", + "name": "xvs", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getXVSBalanceMetadataExt", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "votes", + "type": "uint256" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allocated", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.XVSBalanceMetadataExt", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller", + "type": "address" + } + ], + "name": "pendingRewards", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "distributorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "totalRewards", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.PendingReward[]", + "name": "pendingRewards", + "type": "tuple[]" + } + ], + "internalType": "struct VenusLens.RewardSummary", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address payable", + "name": "account", + "type": "address" + } + ], + "name": "vTokenBalances", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUnderlying", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenAllowance", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.VTokenBalances", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "address payable", + "name": "account", + "type": "address" + } + ], + "name": "vTokenBalancesAll", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUnderlying", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenAllowance", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.VTokenBalances[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "vTokenMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "venusSupplySpeed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "venusBorrowSpeed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dailySupplyXvs", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dailyBorrowXvs", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.VTokenMetadata", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "vTokenMetadataAll", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "venusSupplySpeed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "venusBorrowSpeed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dailySupplyXvs", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dailyBorrowXvs", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.VTokenMetadata[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "vTokenUnderlyingPrice", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "underlyingPrice", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.VTokenUnderlyingPrice", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "vTokenUnderlyingPriceAll", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "underlyingPrice", + "type": "uint256" + } + ], + "internalType": "struct VenusLens.VTokenUnderlyingPrice[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "WBETH": { + "address": "0xf9F98365566F4D55234f24b99caA1AfBE6428D44", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initialAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_tokenName", + "type": "string" + }, + { + "internalType": "uint8", + "name": "_decimalUnits", + "type": "uint8" + }, + { + "internalType": "string", + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "WBNB": { + "address": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "guy", + "type": "address" + }, + { + "name": "wad", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "wad", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "wad", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "deposit", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "src", + "type": "address" + }, + { + "indexed": true, + "name": "guy", + "type": "address" + }, + { + "indexed": false, + "name": "wad", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "src", + "type": "address" + }, + { + "indexed": true, + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "name": "wad", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "name": "wad", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "src", + "type": "address" + }, + { + "indexed": false, + "name": "wad", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + } + ] + }, + "WhitepaperInterestRateModel": { + "address": "0xdE9beC5102ee897a2c934321309517dD6c0106F4", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + } + ] + }, + "XRP": { + "address": "0x3022A32fdAdB4f02281E8Fab33e0A6811237aab0", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": 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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "_decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "XVS": { + "address": "0xB9e0E753630434d7863528cc73CB7AC638a7c8ff", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Freezed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "UnFreezed", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rawAmount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "fromBlock", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "freeze", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getCurrentVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getPriorVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rawAmount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rawAmount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "unfreeze", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "XVSStore": { + "address": "0x7B4dba3b320E7D421A213e1a73bB9858bb6839F8", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnerTransferred", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "emergencyRewardWithdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokens", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "safeRewardTransfer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "name": "setNewAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "setNewOwner", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "status", + "type": "bool" + } + ], + "name": "setRewardToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "XVSVault": { + "address": "0x30EE880177eCE5Bc2f8865fAefa072e7386D4264", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChangedV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChangedV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ExecutedWithdrawal", + "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": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "allocPoints", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lockPeriod", + "type": "uint256" + } + ], + "name": "PoolAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldAllocPoints", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newAllocPoints", + "type": "uint256" + } + ], + "name": "PoolUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RequestedWithdrawal", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldReward", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReward", + "type": "uint256" + } + ], + "name": "RewardAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldXvs", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldStore", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newXvs", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newStore", + "type": "address" + } + ], + "name": "StoreUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldOwedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newOwedAmount", + "type": "uint256" + } + ], + "name": "VaultDebtUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPeriod", + "type": "uint256" + } + ], + "name": "WithdrawalLockingPeriodUpdated", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_LOCK_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IXVSVaultProxy", + "name": "xvsVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV5", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_allocPoint", + "type": "uint256" + }, + { + "internalType": "contract IBEP20", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_rewardPerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lockPeriod", + "type": "uint256" + } + ], + "name": "add", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "fromBlock", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "executeWithdrawal", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getCurrentVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getEligibleWithdrawalAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawalAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getPriorVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getRequestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getUserInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardDebt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pendingWithdrawals", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getWithdrawalRequests", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "lockedUntil", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "afterUpgrade", + "type": "uint128" + } + ], + "internalType": "struct XVSVaultStorageV1.WithdrawalRequest[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isStakedToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingReward", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "pendingRewardTransfers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingWithdrawalsBeforeUpgrade", + "outputs": [ + { + "internalType": "uint256", + "name": "beforeUpgradeWithdrawalAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingXVSVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolInfos", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allocPoint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastRewardBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardPerShare", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockPeriod", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + } + ], + "name": "poolLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "requestWithdrawal", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "resume", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAmountsPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_allocPoint", + "type": "uint256" + } + ], + "name": "set", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_rewardAmount", + "type": "uint256" + } + ], + "name": "setRewardAmountPerBlock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_newPeriod", + "type": "uint256" + } + ], + "name": "setWithdrawalLockingPeriod", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvs", + "type": "address" + }, + { + "internalType": "address", + "name": "_xvsStore", + "type": "address" + } + ], + "name": "setXvsStore", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAllocPoints", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "updatePool", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsStore", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "XVSVaultProxy": { + "address": "0x9aB56bAD2D7631B2A857ccf36d998232A8b82280", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingXVSVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChangedV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChangedV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ExecutedWithdrawal", + "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": "contract IPrime", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IPrime", + "name": "newPrimeToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldPrimeRewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPrimeRewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldPrimePoolId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPrimePoolId", + "type": "uint256" + } + ], + "name": "NewPrimeToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "allocPoints", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lockPeriod", + "type": "uint256" + } + ], + "name": "PoolAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldAllocPoints", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newAllocPoints", + "type": "uint256" + } + ], + "name": "PoolUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RequestedWithdrawal", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldReward", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReward", + "type": "uint256" + } + ], + "name": "RewardAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldXvs", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldStore", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newXvs", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newStore", + "type": "address" + } + ], + "name": "StoreUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldOwedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newOwedAmount", + "type": "uint256" + } + ], + "name": "VaultDebtUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPeriod", + "type": "uint256" + } + ], + "name": "WithdrawalLockingPeriodUpdated", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_LOCK_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IXVSVaultProxy", + "name": "xvsVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV5", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_allocPoint", + "type": "uint256" + }, + { + "internalType": "contract IBEP20", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_rewardPerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lockPeriod", + "type": "uint256" + } + ], + "name": "add", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "fromBlock", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "executeWithdrawal", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getCurrentVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getEligibleWithdrawalAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawalAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getPriorVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getRequestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getUserInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardDebt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pendingWithdrawals", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getWithdrawalRequests", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "lockedUntil", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "afterUpgrade", + "type": "uint128" + } + ], + "internalType": "struct XVSVaultStorageV1.WithdrawalRequest[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isStakedToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingReward", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "pendingRewardTransfers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingWithdrawalsBeforeUpgrade", + "outputs": [ + { + "internalType": "uint256", + "name": "beforeUpgradeWithdrawalAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingXVSVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolInfos", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allocPoint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastRewardBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardPerShare", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockPeriod", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + } + ], + "name": "poolLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "primePoolId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "primeRewardToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "primeToken", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "requestWithdrawal", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "resume", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAmountsPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_allocPoint", + "type": "uint256" + } + ], + "name": "set", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_primeToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_primeRewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_primePoolId", + "type": "uint256" + } + ], + "name": "setPrimeToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_rewardAmount", + "type": "uint256" + } + ], + "name": "setRewardAmountPerBlock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_newPeriod", + "type": "uint256" + } + ], + "name": "setWithdrawalLockingPeriod", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvs", + "type": "address" + }, + { + "internalType": "address", + "name": "_xvsStore", + "type": "address" + } + ], + "name": "setXvsStore", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAllocPoints", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "updatePool", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsStore", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "XVSVaultProxy_Implementation": { + "address": "0x0fdbe58bbf3190d21a0589d0a448682d68de66a2", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChangedV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChangedV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ExecutedWithdrawal", + "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": "contract IPrime", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IPrime", + "name": "newPrimeToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldPrimeRewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPrimeRewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldPrimePoolId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPrimePoolId", + "type": "uint256" + } + ], + "name": "NewPrimeToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "allocPoints", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lockPeriod", + "type": "uint256" + } + ], + "name": "PoolAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldAllocPoints", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newAllocPoints", + "type": "uint256" + } + ], + "name": "PoolUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RequestedWithdrawal", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldReward", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReward", + "type": "uint256" + } + ], + "name": "RewardAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldXvs", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldStore", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newXvs", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newStore", + "type": "address" + } + ], + "name": "StoreUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldOwedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newOwedAmount", + "type": "uint256" + } + ], + "name": "VaultDebtUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPeriod", + "type": "uint256" + } + ], + "name": "WithdrawalLockingPeriodUpdated", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_LOCK_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IXVSVaultProxy", + "name": "xvsVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV5", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_allocPoint", + "type": "uint256" + }, + { + "internalType": "contract IBEP20", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_rewardPerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lockPeriod", + "type": "uint256" + } + ], + "name": "add", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "fromBlock", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "executeWithdrawal", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getCurrentVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getEligibleWithdrawalAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawalAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getPriorVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getRequestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getUserInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardDebt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pendingWithdrawals", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getWithdrawalRequests", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "lockedUntil", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "afterUpgrade", + "type": "uint128" + } + ], + "internalType": "struct XVSVaultStorageV1.WithdrawalRequest[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isStakedToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingReward", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "pendingRewardTransfers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingWithdrawalsBeforeUpgrade", + "outputs": [ + { + "internalType": "uint256", + "name": "beforeUpgradeWithdrawalAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingXVSVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolInfos", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allocPoint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastRewardBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardPerShare", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockPeriod", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + } + ], + "name": "poolLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "primePoolId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "primeRewardToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "primeToken", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "requestWithdrawal", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "resume", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAmountsPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_allocPoint", + "type": "uint256" + } + ], + "name": "set", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_primeToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_primeRewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_primePoolId", + "type": "uint256" + } + ], + "name": "setPrimeToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_rewardAmount", + "type": "uint256" + } + ], + "name": "setRewardAmountPerBlock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_newPeriod", + "type": "uint256" + } + ], + "name": "setWithdrawalLockingPeriod", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvs", + "type": "address" + }, + { + "internalType": "address", + "name": "_xvsStore", + "type": "address" + } + ], + "name": "setXvsStore", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAllocPoints", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "updatePool", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsStore", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "XVSVaultProxy_Proxy": { + "address": "0x9aB56bAD2D7631B2A857ccf36d998232A8b82280", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingXVSVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "XVSVesting": { + "address": "0x9667B6E438232925525F26CeC0acC3A39B9980C8", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrtConversionAddress", + "type": "address" + } + ], + "name": "VRTConversionSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountClaimed", + "type": "uint256" + } + ], + "name": "VestedTokensClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + } + ], + "name": "XVSVested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "XVSWithdrawn", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "TOTAL_VESTING_TIME", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract XVSVestingProxy", + "name": "xvsVestingProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_notEntered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "depositAmount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCurrentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getWithdrawableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "totalWithdrawableAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalVestedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalWithdrawnAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvsAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "initialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_vrtConversionAddress", + "type": "address" + } + ], + "name": "setVRTConverter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "vestings", + "outputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vrtConversionAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvs", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsDecimalsMultiplier", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "XVSVestingProxy": { + "address": "0xcfa3a6bc934EcA22fa39e854c823cD3dE79D9BC8", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "address", + "name": "_xvsAddress", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrtConversionAddress", + "type": "address" + } + ], + "name": "VRTConversionSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountClaimed", + "type": "uint256" + } + ], + "name": "VestedTokensClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + } + ], + "name": "XVSVested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "XVSWithdrawn", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "TOTAL_VESTING_TIME", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract XVSVestingProxy", + "name": "xvsVestingProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_notEntered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "depositAmount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCurrentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getWithdrawableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "totalWithdrawableAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalVestedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalWithdrawnAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvsAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "initialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_vrtConversionAddress", + "type": "address" + } + ], + "name": "setVRTConverter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "vestings", + "outputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vrtConversionAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvs", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsDecimalsMultiplier", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "XVSVestingProxy_Implementation": { + "address": "0x9667b6e438232925525f26cec0acc3a39b9980c8", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrtConversionAddress", + "type": "address" + } + ], + "name": "VRTConversionSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountClaimed", + "type": "uint256" + } + ], + "name": "VestedTokensClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + } + ], + "name": "XVSVested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "XVSWithdrawn", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "TOTAL_VESTING_TIME", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract XVSVestingProxy", + "name": "xvsVestingProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_notEntered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "depositAmount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCurrentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getWithdrawableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "totalWithdrawableAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalVestedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalWithdrawnAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvsAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "initialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_vrtConversionAddress", + "type": "address" + } + ], + "name": "setVRTConverter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "vestings", + "outputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vrtConversionAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvs", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsDecimalsMultiplier", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "XVSVestingProxy_Proxy": { + "address": "0xcfa3a6bc934EcA22fa39e854c823cD3dE79D9BC8", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "address", + "name": "_xvsAddress", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "pancakeFactory": { + "address": "0x182859893230dC89b114d6e2D547BFFE30474a21", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_feeToSetter", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "INIT_CODE_PAIR_HASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "feeTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "feeToSetter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_feeTo", + "type": "address" + } + ], + "name": "setFeeTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_feeToSetter", + "type": "address" + } + ], + "name": "setFeeToSetter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "vBNB": { + "address": "0x2E7222e51c0f6e98610A1543Aa3836E092CDe62c", + "abi": [ + { + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "mint", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "repayBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "repayBorrowBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "vBTC": { + "address": "0xb6e9322C49FD75a367Fcb17B0Fcd62C5070EbCBe", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vBTC_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vBTC_Proxy": { + "address": "0xb6e9322C49FD75a367Fcb17B0Fcd62C5070EbCBe", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vBUSD": { + "address": "0x08e0A5575De71037aE36AbfAfb516595fE68e5e4", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vBUSD_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vBUSD_Proxy": { + "address": "0x08e0A5575De71037aE36AbfAfb516595fE68e5e4", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vBep20Delegate": { + "address": "0xAF1b4826c8396A99139af3c9359044D34c8d1f1f", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vETH": { + "address": "0x162D005F0Fff510E54958Cfc5CF32A3180A84aab", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vETH_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vETH_Proxy": { + "address": "0x162D005F0Fff510E54958Cfc5CF32A3180A84aab", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vLTC": { + "address": "0xAfc13BC065ABeE838540823431055D2ea52eBA52", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vLTC_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vLTC_Proxy": { + "address": "0xAfc13BC065ABeE838540823431055D2ea52eBA52", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vSXP": { + "address": "0x74469281310195A04840Daf6EdF576F559a3dE80", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vSXP_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vSXP_Proxy": { + "address": "0x74469281310195A04840Daf6EdF576F559a3dE80", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vTRX": { + "address": "0x369Fea97f6fB7510755DCA389088d9E2e2819278", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vTRX_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vTRX_Proxy": { + "address": "0x369Fea97f6fB7510755DCA389088d9E2e2819278", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vTUSD": { + "address": "0xEFAACF73CE2D38ED40991f29E72B12C74bd4cf23", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vTUSD_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vTUSD_Proxy": { + "address": "0xEFAACF73CE2D38ED40991f29E72B12C74bd4cf23", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vUSDC": { + "address": "0xD5C4C2e2facBEB59D0216D0595d63FcDc6F9A1a7", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vUSDC_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vUSDC_Proxy": { + "address": "0xD5C4C2e2facBEB59D0216D0595d63FcDc6F9A1a7", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vUSDT": { + "address": "0xb7526572FFE56AB9D7489838Bf2E18e3323b441A", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vUSDT_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vUSDT_Proxy": { + "address": "0xb7526572FFE56AB9D7489838Bf2E18e3323b441A", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vWBETH": { + "address": "0x35566ED3AF9E537Be487C98b1811cDf95ad0C32b", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vWBETH_Implementation": { + "address": "0xc01902dbf72c2ccbfebadb9b7a9e23577893d3a3", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vWBETH_Proxy": { + "address": "0x35566ED3AF9E537Be487C98b1811cDf95ad0C32b", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vXRP": { + "address": "0x488aB2826a154da01CC4CC16A8C83d4720D3cA2C", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vXRP_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vXRP_Proxy": { + "address": "0x488aB2826a154da01CC4CC16A8C83d4720D3cA2C", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vXVS": { + "address": "0x6d6F697e34145Bb95c54E77482d97cc261Dc237E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vXVS_Implementation": { + "address": "0x8d79c8f4400fe68fd17040539fe5e1706c1f2850", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "_becomeImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount_", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_resignImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel_", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlManagerAddress", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "protcolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReduceReservesBlockDelta_", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "vXVS_Proxy": { + "address": "0x6d6F697e34145Bb95c54E77482d97cc261Dc237E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address payable", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "_addReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowResign", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "becomeImplementationData", + "type": "bytes" + } + ], + "name": "_setImplementation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "delegateToViewImplementation", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] + }, + "ProtocolShareReserve": { + "address": "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E3", + "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": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "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": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "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": "uint8", + "name": "oldPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "newPercentage", + "type": "uint8" + }, + { + "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": "uint8", + "name": "", + "type": "uint8" + } + ], + "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": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "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": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "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": "0x6A7FF4641F52b267102a5a0779cE7a060374d6cC", + "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": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "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": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "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": "uint8", + "name": "oldPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "newPercentage", + "type": "uint8" + }, + { + "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": "uint8", + "name": "", + "type": "uint8" + } + ], + "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": "uint256", - "name": "totalRewards", - "type": "uint256" + "internalType": "uint8", + "name": "percentage", + "type": "uint8" }, { - "components": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct VenusLens.PendingReward[]", - "name": "pendingRewards", - "type": "tuple[]" + "internalType": "address", + "name": "destination", + "type": "address" } ], - "internalType": "struct VenusLens.RewardSummary", + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", "name": "", - "type": "tuple" + "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": "uint8", + "name": "percentage", + "type": "uint8" + }, + { + "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" } ], - "payable": false, - "stateMutability": "view", + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { - "internalType": "contract VToken", - "name": "vToken", + "internalType": "address", + "name": "_poolRegistry", "type": "address" - }, + } + ], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "internalType": "address payable", - "name": "account", + "internalType": "address", + "name": "", "type": "address" } ], - "name": "vTokenBalances", + "name": "totalAssetReserve", "outputs": [ { - "components": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balanceOf", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "borrowBalanceCurrent", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "balanceOfUnderlying", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokenBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokenAllowance", - "type": "uint256" - } - ], - "internalType": "struct VenusLens.VTokenBalances", + "internalType": "uint256", "name": "", - "type": "tuple" + "type": "uint256" } ], - "payable": false, + "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" }, { - "constant": false, "inputs": [ { - "internalType": "contract VToken[]", - "name": "vTokens", - "type": "address[]" + "internalType": "address", + "name": "comptroller", + "type": "address" }, { - "internalType": "address payable", - "name": "account", + "internalType": "address", + "name": "asset", "type": "address" + }, + { + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" } ], - "name": "vTokenBalancesAll", + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", "outputs": [ { - "components": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balanceOf", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "borrowBalanceCurrent", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "balanceOfUnderlying", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokenBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokenAllowance", - "type": "uint256" - } - ], - "internalType": "struct VenusLens.VTokenBalances[]", + "internalType": "address", "name": "", - "type": "tuple[]" + "type": "address" } ], - "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" + } + ] + }, + "ProtocolShareReserve_Proxy": { + "address": "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E3", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" }, { - "constant": false, + "anonymous": false, "inputs": [ { - "internalType": "contract VToken", - "name": "vToken", + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "name": "vTokenMetadata", - "outputs": [ + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "components": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "exchangeRateCurrent", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "supplyRatePerBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "borrowRatePerBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveFactorMantissa", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalBorrows", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalReserves", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalSupply", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalCash", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "isListed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "collateralFactorMantissa", - "type": "uint256" - }, - { - "internalType": "address", - "name": "underlyingAssetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "vTokenDecimals", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "underlyingDecimals", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "venusSupplySpeed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "venusBorrowSpeed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dailySupplyXvs", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dailyBorrowXvs", - "type": "uint256" - } - ], - "internalType": "struct VenusLens.VTokenMetadata", - "name": "", - "type": "tuple" + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" } ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { - "internalType": "contract VToken[]", - "name": "vTokens", - "type": "address[]" + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" } ], - "name": "vTokenMetadataAll", + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", "outputs": [ { - "components": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "exchangeRateCurrent", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "supplyRatePerBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "borrowRatePerBlock", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserveFactorMantissa", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalBorrows", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalReserves", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalSupply", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalCash", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "isListed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "collateralFactorMantissa", - "type": "uint256" - }, - { - "internalType": "address", - "name": "underlyingAssetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "vTokenDecimals", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "underlyingDecimals", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "venusSupplySpeed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "venusBorrowSpeed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dailySupplyXvs", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dailyBorrowXvs", - "type": "uint256" - } - ], - "internalType": "struct VenusLens.VTokenMetadata[]", - "name": "", - "type": "tuple[]" + "internalType": "address", + "name": "admin_", + "type": "address" } ], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [ { - "internalType": "contract VToken", - "name": "vToken", + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "name": "vTokenUnderlyingPrice", + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", "outputs": [ { - "components": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "underlyingPrice", - "type": "uint256" - } - ], - "internalType": "struct VenusLens.VTokenUnderlyingPrice", - "name": "", - "type": "tuple" + "internalType": "address", + "name": "implementation_", + "type": "address" } ], - "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [ { - "internalType": "contract VToken[]", - "name": "vTokens", - "type": "address[]" + "internalType": "address", + "name": "newImplementation", + "type": "address" } ], - "name": "vTokenUnderlyingPriceAll", - "outputs": [ + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "components": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "underlyingPrice", - "type": "uint256" - } - ], - "internalType": "struct VenusLens.VTokenUnderlyingPrice[]", - "name": "", - "type": "tuple[]" + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "payable": false, - "stateMutability": "view", + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" } ] } diff --git a/deployments/bsctestnet/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json b/deployments/bsctestnet/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json new file mode 100644 index 000000000..45eca5fe5 --- /dev/null +++ b/deployments/bsctestnet/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json @@ -0,0 +1,497 @@ +{ + "address": "0xb7C5A751CCa00b11AF3CA4A35e9e992f0f9c9c9c", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xedf3b054dcf4919fb405fb850c06ec3b3cd9c715db095643df750c548160f3af", + "receipt": { + "to": null, + "from": "0x03862dFa5D0be8F64509C001cb8C6188194469DF", + "contractAddress": "0xb7C5A751CCa00b11AF3CA4A35e9e992f0f9c9c9c", + "transactionIndex": 0, + "gasUsed": "554524", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000000000000000000000000000040000000020000000000000000000000000000000000000000000000000000008000000000000000000000000000000", + "blockHash": "0x902eac2d68c8eaadda9ad70a654ec5b7723e0b275d30eac146ca0769bc06e22c", + "transactionHash": "0xedf3b054dcf4919fb405fb850c06ec3b3cd9c715db095643df750c548160f3af", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 34736953, + "transactionHash": "0xedf3b054dcf4919fb405fb850c06ec3b3cd9c715db095643df750c548160f3af", + "address": "0xb7C5A751CCa00b11AF3CA4A35e9e992f0f9c9c9c", + "topics": ["0x6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d"], + "data": "0x0000000000000000000000000000000000000000000000000000000071672e7f000000000000000000000000000000000000000000000000000000046e07d0f60000000000000000000000000000000000000000000000000000004272753e6d000000000000000000000000000000000000000000000000063eb89da4ed0000", + "logIndex": 0, + "blockHash": "0x902eac2d68c8eaadda9ad70a654ec5b7723e0b275d30eac146ca0769bc06e22c" + } + ], + "blockNumber": 34736953, + "cumulativeGasUsed": "554524", + "status": 1, + "byzantium": true + }, + "args": [ + "20000000000000000", + "200000000000000000", + "3000000000000000000", + "450000000000000000", + "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA" + ], + "numDeployments": 1, + "solcInputHash": "82cd33260a9b17bbce6d70381b9dc2d8", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"},{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":false,\"internalType\":\"uint256\",\"name\":\"baseRatePerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"kink\",\"type\":\"uint256\"}],\"name\":\"NewInterestParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"jumpMultiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"kink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"multiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"}],\"name\":\"updateJumpRateModel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"utilizationRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Arr00\",\"kind\":\"dev\",\"methods\":{\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The borrow rate percentage per block as a mantissa (scaled by 1e18)\"}},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserveFactorMantissa\":\"The current reserve factor for the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\"}},\"isInterestRateModel()\":{\"returns\":{\"_0\":\"Always true\"}},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized if the sender is not allowed to call this function\",\"params\":{\"baseRatePerYear\":\"The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\",\"jumpMultiplierPerYear\":\"The multiplierPerBlock after hitting a specified utilization point\",\"kink_\":\"The utilization point at which the jump multiplier is applied\",\"multiplierPerYear\":\"The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\"}},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market (currently unused)\"},\"returns\":{\"_0\":\"The utilization rate as a mantissa between [0, MANTISSA_ONE]\"}}},\"title\":\"Compound's JumpRateModel Contract V2 for V2 vTokens\",\"version\":1},\"userdoc\":{\"errors\":{\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}]},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"The address of the AccessControlManager contract\"},\"baseRatePerBlock()\":{\"notice\":\"The base interest rate which is the y-intercept when utilization rate is 0\"},\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current borrow rate per block\"},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current supply rate per block\"},\"isInterestRateModel()\":{\"notice\":\"Indicator that this is an InterestRateModel contract (for inspection)\"},\"jumpMultiplierPerBlock()\":{\"notice\":\"The multiplier per block after hitting a specified utilization point\"},\"kink()\":{\"notice\":\"The utilization point at which the jump multiplier is applied\"},\"multiplierPerBlock()\":{\"notice\":\"The multiplier of utilization rate that gives the slope of the interest rate\"},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"notice\":\"Update the parameters of the interest rate model\"},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\"}},\"notice\":\"Supports only for V2 vTokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JumpRateModelV2.sol\":\"JumpRateModelV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\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\":\"0x41deef84d1839590b243b66506691fde2fb938da01eabde53e82d3b8316fdaf9\",\"license\":\"BSD-3-Clause\"},\"contracts/BaseJumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { BLOCKS_PER_YEAR, EXP_SCALE, MANTISSA_ONE } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Logic for Compound's JumpRateModel Contract V2.\\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\\n */\\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\\n /**\\n * @notice The address of the AccessControlManager contract\\n */\\n IAccessControlManagerV8 public accessControlManager;\\n\\n /**\\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\\n */\\n uint256 public multiplierPerBlock;\\n\\n /**\\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\\n */\\n uint256 public baseRatePerBlock;\\n\\n /**\\n * @notice The multiplier per block after hitting a specified utilization point\\n */\\n uint256 public jumpMultiplierPerBlock;\\n\\n /**\\n * @notice The utilization point at which the jump multiplier is applied\\n */\\n uint256 public kink;\\n\\n event NewInterestParams(\\n uint256 baseRatePerBlock,\\n uint256 multiplierPerBlock,\\n uint256 jumpMultiplierPerBlock,\\n uint256 kink\\n );\\n\\n /**\\n * @notice Thrown when the action is prohibited by AccessControlManager\\n */\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Construct an interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @param accessControlManager_ The address of the AccessControlManager contract\\n */\\n constructor(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n ) {\\n require(address(accessControlManager_) != address(0), \\\"invalid ACM address\\\");\\n\\n accessControlManager = accessControlManager_;\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @custom:error Unauthorized if the sender is not allowed to call this function\\n * @custom:access Controlled by AccessControlManager\\n */\\n function updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) external virtual {\\n string memory signature = \\\"updateJumpRateModel(uint256,uint256,uint256,uint256)\\\";\\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Calculates the current supply rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param reserveFactorMantissa The current reserve factor for the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) public view virtual override returns (uint256) {\\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\\n uint256 incomeToDistribute = borrows * rateToPool;\\n uint256 supply = cash + borrows + badDebt - reserves;\\n return incomeToDistribute / supply;\\n }\\n\\n /**\\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market (currently unused)\\n * @param badDebt The amount of badDebt in the market\\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\\n */\\n function utilizationRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) public pure returns (uint256) {\\n // Utilization rate is 0 when there are no borrows and badDebt\\n if ((borrows + badDebt) == 0) {\\n return 0;\\n }\\n\\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\\n\\n if (rate > EXP_SCALE) {\\n rate = EXP_SCALE;\\n }\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Internal function to update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n */\\n function _updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) internal {\\n baseRatePerBlock = baseRatePerYear / BLOCKS_PER_YEAR;\\n multiplierPerBlock = multiplierPerYear / BLOCKS_PER_YEAR;\\n jumpMultiplierPerBlock = jumpMultiplierPerYear / BLOCKS_PER_YEAR;\\n kink = kink_;\\n\\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function _getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) internal view returns (uint256) {\\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\\n uint256 kink_ = kink;\\n\\n if (util <= kink_) {\\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n }\\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n uint256 excessUtil;\\n unchecked {\\n excessUtil = util - kink_;\\n }\\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\\n }\\n}\\n\",\"keccak256\":\"0xaaceeecdb6212410755c76c61024f235f105279cd3b040f4d43578276243754b\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"contracts/JumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { BaseJumpRateModelV2 } from \\\"./BaseJumpRateModelV2.sol\\\";\\n\\n/**\\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\\n * @author Arr00\\n * @notice Supports only for V2 vTokens\\n */\\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\\n constructor(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n )\\n BaseJumpRateModelV2(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_, accessControlManager_)\\n /* solhint-disable-next-line no-empty-blocks */\\n {\\n\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view override returns (uint256) {\\n return _getBorrowRate(cash, borrows, reserves, badDebt);\\n }\\n}\\n\",\"keccak256\":\"0x4ed1afa149d27fbe7ac0f6099c90be41304aff5e45c81b390c357eb5391699c5\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev The approximate number of blocks per year that is assumed by the interest rate model\\nuint256 constant BLOCKS_PER_YEAR = 10_512_000;\\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\",\"keccak256\":\"0x04cd899695ea593a2529cb6a1a04c2a34bff0c1516bd70a5f638ae7a850cad8b\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506040516108be3803806108be83398101604081905261002f91610150565b84848484846001600160a01b03811661008e5760405162461bcd60e51b815260206004820152601360248201527f696e76616c69642041434d206164647265737300000000000000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b0383161790556100b5858585856100c4565b505050505050505050506101cd565b6100d162a06680856101ab565b6002556100e162a06680846101ab565b6001556100f162a06680836101ab565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b600080600080600060a0868803121561016857600080fd5b855160208701516040880151606089015160808a0151939850919650945092506001600160a01b038116811461019d57600080fd5b809150509295509295909350565b6000826101c857634e487b7160e01b600052601260045260246000fd5b500490565b6106e2806101dc6000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c80638726bb89116100665780638726bb8914610113578063b4a0bdf31461011c578063b9f9850a14610147578063f14039de14610150578063fd2da3391461015957600080fd5b8063073b8a74146100a35780630cde8d1c146100c95780632037f3e7146100dc5780632191f92a146100f157806370d3c43f14610100575b600080fd5b6100b66100b13660046104bf565b610162565b6040519081526020015b60405180910390f35b6100b66100d73660046104f1565b61017b565b6100ef6100ea3660046104bf565b61020e565b005b604051600181526020016100c0565b6100b661010e3660046104bf565b6102e5565b6100b660015481565b60005461012f906001600160a01b031681565b6040516001600160a01b0390911681526020016100c0565b6100b660035481565b6100b660025481565b6100b660045481565b60006101708585858561036e565b90505b949350505050565b60008061019084670de0b6b3a7640000610542565b905060006101a08888888761036e565b90506000670de0b6b3a76400006101b78484610559565b6101c19190610578565b905060006101cf828a610559565b9050600088876101df8c8e61059a565b6101e9919061059a565b6101f39190610542565b90506101ff8183610578565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161067960349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab9061026190339086906004016105ff565b602060405180830381865afa15801561027e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a29190610623565b9050806102d157333083604051634a3fa29360e01b81526004016102c89392919061064c565b60405180910390fd5b6102dd86868686610433565b505050505050565b60006102f1828561059a565b60000361030057506000610173565b6000838361030e878961059a565b610318919061059a565b6103229190610542565b670de0b6b3a7640000610335858861059a565b61033f9190610559565b6103499190610578565b9050670de0b6b3a76400008111156101705750670de0b6b3a764000095945050505050565b60008061037d868686866102e5565b6004549091508082116103c157600254670de0b6b3a7640000600154846103a49190610559565b6103ae9190610578565b6103b8919061059a565b92505050610173565b6000600254670de0b6b3a7640000600154846103dd9190610559565b6103e79190610578565b6103f1919061059a565b90506000828403905081670de0b6b3a7640000600354836104129190610559565b61041c9190610578565b610426919061059a565b9998505050505050505050565b61044062a0668085610578565b60025561045062a0668084610578565b60015561046062a0668083610578565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b600080600080608085870312156104d557600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561050957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105545761055461052c565b500390565b60008160001904831182151516156105735761057361052c565b500290565b60008261059557634e487b7160e01b600052601260045260246000fd5b500490565b600082198211156105ad576105ad61052c565b500190565b6000815180845260005b818110156105d8576020818501810151868301820152016105bc565b818111156105ea576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090610173908301846105b2565b60006020828403121561063557600080fd5b8151801515811461064557600080fd5b9392505050565b6001600160a01b03848116825283166020820152606060408201819052600090610170908301846105b256fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a26469706673582212206a37cebdb4b862acc229f004fa6e49bdd6e972410e73f5a533c3930dca0b66a464736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061009e5760003560e01c80638726bb89116100665780638726bb8914610113578063b4a0bdf31461011c578063b9f9850a14610147578063f14039de14610150578063fd2da3391461015957600080fd5b8063073b8a74146100a35780630cde8d1c146100c95780632037f3e7146100dc5780632191f92a146100f157806370d3c43f14610100575b600080fd5b6100b66100b13660046104bf565b610162565b6040519081526020015b60405180910390f35b6100b66100d73660046104f1565b61017b565b6100ef6100ea3660046104bf565b61020e565b005b604051600181526020016100c0565b6100b661010e3660046104bf565b6102e5565b6100b660015481565b60005461012f906001600160a01b031681565b6040516001600160a01b0390911681526020016100c0565b6100b660035481565b6100b660025481565b6100b660045481565b60006101708585858561036e565b90505b949350505050565b60008061019084670de0b6b3a7640000610542565b905060006101a08888888761036e565b90506000670de0b6b3a76400006101b78484610559565b6101c19190610578565b905060006101cf828a610559565b9050600088876101df8c8e61059a565b6101e9919061059a565b6101f39190610542565b90506101ff8183610578565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161067960349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab9061026190339086906004016105ff565b602060405180830381865afa15801561027e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a29190610623565b9050806102d157333083604051634a3fa29360e01b81526004016102c89392919061064c565b60405180910390fd5b6102dd86868686610433565b505050505050565b60006102f1828561059a565b60000361030057506000610173565b6000838361030e878961059a565b610318919061059a565b6103229190610542565b670de0b6b3a7640000610335858861059a565b61033f9190610559565b6103499190610578565b9050670de0b6b3a76400008111156101705750670de0b6b3a764000095945050505050565b60008061037d868686866102e5565b6004549091508082116103c157600254670de0b6b3a7640000600154846103a49190610559565b6103ae9190610578565b6103b8919061059a565b92505050610173565b6000600254670de0b6b3a7640000600154846103dd9190610559565b6103e79190610578565b6103f1919061059a565b90506000828403905081670de0b6b3a7640000600354836104129190610559565b61041c9190610578565b610426919061059a565b9998505050505050505050565b61044062a0668085610578565b60025561045062a0668084610578565b60015561046062a0668083610578565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b600080600080608085870312156104d557600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561050957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105545761055461052c565b500390565b60008160001904831182151516156105735761057361052c565b500290565b60008261059557634e487b7160e01b600052601260045260246000fd5b500490565b600082198211156105ad576105ad61052c565b500190565b6000815180845260005b818110156105d8576020818501810151868301820152016105bc565b818111156105ea576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090610173908301846105b2565b60006020828403121561063557600080fd5b8151801515811461064557600080fd5b9392505050565b6001600160a01b03848116825283166020820152606060408201819052600090610170908301846105b256fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a26469706673582212206a37cebdb4b862acc229f004fa6e49bdd6e972410e73f5a533c3930dca0b66a464736f6c634300080d0033", + "devdoc": { + "author": "Arr00", + "kind": "dev", + "methods": { + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The borrow rate percentage per block as a mantissa (scaled by 1e18)" + } + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserveFactorMantissa": "The current reserve factor for the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)" + } + }, + "isInterestRateModel()": { + "returns": { + "_0": "Always true" + } + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized if the sender is not allowed to call this function", + "params": { + "baseRatePerYear": "The approximate target base APR, as a mantissa (scaled by EXP_SCALE)", + "jumpMultiplierPerYear": "The multiplierPerBlock after hitting a specified utilization point", + "kink_": "The utilization point at which the jump multiplier is applied", + "multiplierPerYear": "The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)" + } + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market (currently unused)" + }, + "returns": { + "_0": "The utilization rate as a mantissa between [0, MANTISSA_ONE]" + } + } + }, + "title": "Compound's JumpRateModel Contract V2 for V2 vTokens", + "version": 1 + }, + "userdoc": { + "errors": { + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ] + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "The address of the AccessControlManager contract" + }, + "baseRatePerBlock()": { + "notice": "The base interest rate which is the y-intercept when utilization rate is 0" + }, + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current borrow rate per block" + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current supply rate per block" + }, + "isInterestRateModel()": { + "notice": "Indicator that this is an InterestRateModel contract (for inspection)" + }, + "jumpMultiplierPerBlock()": { + "notice": "The multiplier per block after hitting a specified utilization point" + }, + "kink()": { + "notice": "The utilization point at which the jump multiplier is applied" + }, + "multiplierPerBlock()": { + "notice": "The multiplier of utilization rate that gives the slope of the interest rate" + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "notice": "Update the parameters of the interest rate model" + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`" + } + }, + "notice": "Supports only for V2 vTokens", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7416, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "accessControlManager", + "offset": 0, + "slot": "0", + "type": "t_contract(IAccessControlManagerV8)5203" + }, + { + "astId": 7419, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "multiplierPerBlock", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 7422, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "baseRatePerBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 7425, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "jumpMultiplierPerBlock", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 7428, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "kink", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_contract(IAccessControlManagerV8)5203": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/bsctestnet/MockPLANET.json b/deployments/bsctestnet/MockPLANET.json new file mode 100644 index 000000000..3a74e3700 --- /dev/null +++ b/deployments/bsctestnet/MockPLANET.json @@ -0,0 +1,450 @@ +{ + "address": "0x52b4E1A2ba407813F829B4b3943A1e57768669A9", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xffaa5f28c07ef5c196a746497f29aabac2c7e41ac06639db0a06db13e898f0d9", + "receipt": { + "to": null, + "from": "0x03862dFa5D0be8F64509C001cb8C6188194469DF", + "contractAddress": "0x52b4E1A2ba407813F829B4b3943A1e57768669A9", + "transactionIndex": 1, + "gasUsed": "636004", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x75d84832259fb905f80401b1531af6ea4205ad86ffdcc68c4ffa71e5373f4978", + "transactionHash": "0xffaa5f28c07ef5c196a746497f29aabac2c7e41ac06639db0a06db13e898f0d9", + "logs": [], + "blockNumber": 34736882, + "cumulativeGasUsed": "667245", + "status": 1, + "byzantium": true + }, + "args": ["PLANET", "PLANET", 18], + "numDeployments": 1, + "solcInputHash": "82cd33260a9b17bbce6d70381b9dc2d8", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"faucet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Mocks/MockToken.sol\":\"MockToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"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\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/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(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {\\n _decimals = decimals_;\\n }\\n\\n function faucet(uint256 amount) external {\\n _mint(msg.sender, amount);\\n }\\n\\n function decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x60985130406108e7c07e140da7ba3c71f94ae0fbb658cffdeee7758fc2f33a8d\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162000c4838038062000c488339810160408190526200003491620001e8565b8251839083906200004d90600390602085019062000075565b5080516200006390600490602084019062000075565b50505060ff1660805250620002a99050565b82805462000083906200026d565b90600052602060002090601f016020900481019282620000a75760008555620000f2565b82601f10620000c257805160ff1916838001178555620000f2565b82800160010185558215620000f2579182015b82811115620000f2578251825591602001919060010190620000d5565b506200010092915062000104565b5090565b5b8082111562000100576000815560010162000105565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014357600080fd5b81516001600160401b03808211156200016057620001606200011b565b604051601f8301601f19908116603f011681019082821181831017156200018b576200018b6200011b565b81604052838152602092508683858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b83821115620001de5760008385830101525b9695505050505050565b600080600060608486031215620001fe57600080fd5b83516001600160401b03808211156200021657600080fd5b620002248783880162000131565b945060208601519150808211156200023b57600080fd5b506200024a8682870162000131565b925050604084015160ff811681146200026257600080fd5b809150509250925092565b600181811c908216806200028257607f821691505b602082108103620002a357634e487b7160e01b600052602260045260246000fd5b50919050565b608051610983620002c5600039600061012601526109836000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea26469706673582212200edbd9e1418eb52e2d269095e1f96654d0216eaadc9e1421f9f01d70e09ac4fa64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea26469706673582212200edbd9e1418eb52e2d269095e1f96654d0216eaadc9e1421f9f01d70e09ac4fa64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2454, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 2460, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 2462, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 2464, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 2466, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "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_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/bsctestnet/ProtocolShareReserve_Implementation.json b/deployments/bsctestnet/ProtocolShareReserve_Implementation.json deleted file mode 100644 index 003b40eda..000000000 --- a/deployments/bsctestnet/ProtocolShareReserve_Implementation.json +++ /dev/null @@ -1,711 +0,0 @@ -{ - "address": "0x0Bbea4B14f475bF5eb60Fc2b0Ca90d3d089Ef833", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "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": "comptroller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsReleased", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "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": "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": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "assetsReserves", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "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": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "protocolIncome_", - "type": "address" - }, - { - "internalType": "address", - "name": "riskFund_", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "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": [], - "name": "protocolIncome", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "releaseFunds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "riskFund", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "poolRegistry_", - "type": "address" - } - ], - "name": "setPoolRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "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" - } - ], - "transactionHash": "0xeb588de1914c19fd30e93f35342a9d0f19152bfb99aaee209179065c17cf4235", - "receipt": { - "to": null, - "from": "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706", - "contractAddress": "0x0Bbea4B14f475bF5eb60Fc2b0Ca90d3d089Ef833", - "transactionIndex": 2, - "gasUsed": "1213372", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000040000000000000000000000000000000000000000020000000000000000", - "blockHash": "0x019959c7a75adaec5bc40cb888ad52c0539a19496e9d70f5cca2e1aaf613cd61", - "transactionHash": "0xeb588de1914c19fd30e93f35342a9d0f19152bfb99aaee209179065c17cf4235", - "logs": [ - { - "transactionIndex": 2, - "blockNumber": 33267950, - "transactionHash": "0xeb588de1914c19fd30e93f35342a9d0f19152bfb99aaee209179065c17cf4235", - "address": "0x0Bbea4B14f475bF5eb60Fc2b0Ca90d3d089Ef833", - "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], - "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 1, - "blockHash": "0x019959c7a75adaec5bc40cb888ad52c0539a19496e9d70f5cca2e1aaf613cd61" - } - ], - "blockNumber": 33267950, - "cumulativeGasUsed": "1325695", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "394b060e0e484d4aa39aea929deecf07", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"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\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FundsReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"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\":\"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\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"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\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"protocolIncome_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"riskFund_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":[],\"name\":\"protocolIncome\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"releaseFunds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"riskFund\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"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\":{\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"getPoolAssetReserve(address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when asset address is zero\",\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Asset's reserve in risk fund.\"}},\"initialize(address,address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when protocol income address is zeroZeroAddressNotAllowed is thrown when risk fund address is zero\",\"params\":{\"protocolIncome_\":\"The address protocol income will be sent to\",\"riskFund_\":\"Risk fund address\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"releaseFunds(address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when asset address is zero\",\"params\":{\"amount\":\"Amount to release\",\"asset\":\"Asset to be released\",\"comptroller\":\"Pool's Comptroller\"},\"returns\":{\"_0\":\"Number of total released tokens\"}},\"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.\"},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"sweepToken(address,address)\":{\"custom:access\":\"Only Owner\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when asset address is zero\",\"params\":{\"_to\":\"Recipient of the output tokens.\",\"_token\":\"The address of the BEP-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)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool)\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"FundsReleased(address,address,uint256)\":{\"notice\":\"Emitted when funds are released\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"}},\"kind\":\"user\",\"methods\":{\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"initialize(address,address)\":{\"notice\":\"Initializes the deployer to owner.\"},\"releaseFunds(address,address,uint256)\":{\"notice\":\"Release funds\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter.\"},\"sweepToken(address,address)\":{\"notice\":\"A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/ProtocolShareReserve.sol\":\"ProtocolShareReserve\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"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/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.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"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 Venus Access Control Contract.\\n * @dev The AccessControlledV8 contract is a wrapper around the OpenZeppelin AccessControl contract\\n * It provides a standardized way to control access to methods within the Venus Smart Contract Ecosystem.\\n * The contract allows the owner to set an AccessControlManager contract address.\\n * It can restrict method calls based on the sender's role and the method's signature.\\n */\\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\":\"0x618d942756b93e02340a42f3c80aa99fc56be1a96861f5464dc23a76bf30b3a5\",\"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\\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\":\"0x41deef84d1839590b243b66506691fde2fb938da01eabde53e82d3b8316fdaf9\",\"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\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor is changed by admin\\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\n\\n /// @notice Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow.\\n * @param vTokenAddress The address of the asset to be removed\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return NO_ERROR;\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(\\n address vToken,\\n address minter,\\n uint256 mintAmount\\n ) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(\\n address vToken,\\n address borrower,\\n uint256 borrowAmount\\n ) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if the market is deprecated or it is a forced liquidation */\\n if (skipLiquidityCheck || isDeprecated(VToken(vTokenBorrowed))) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external override {\\n _checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = accountAssets[user];\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = accountAssets[borrower];\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n _ensureMaxLoops(numMarkets);\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(\\n VToken[] calldata marketsList,\\n Action[] calldata actionsList,\\n bool paused\\n ) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(address account)\\n external\\n view\\n returns (\\n uint256 error,\\n uint256 liquidity,\\n uint256 shortfall\\n )\\n {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(address account)\\n external\\n view\\n returns (\\n uint256 error,\\n uint256 liquidity,\\n uint256 shortfall\\n )\\n {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall Hypothetical account shortfall below collateral requirements\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n )\\n external\\n view\\n returns (\\n uint256 error,\\n uint256 liquidity,\\n uint256 shortfall\\n )\\n {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Check if a market is marked as listed (active)\\n * @param vToken vToken Address for the market to check\\n * @return listed True if listed otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].isListed;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n VToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the market specified, otherwise false.\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = accountAssets[account];\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\n }\\n\\n /**\\n * @notice Check if a vToken market has been deprecated\\n * @dev All borrows in a deprecated vToken market can be immediately liquidated\\n * @param vToken The market to check if deprecated\\n * @return deprecated True if the given vToken market has been deprecated\\n */\\n function isDeprecated(VToken vToken) public view returns (bool) {\\n return\\n markets[address(vToken)].collateralFactorMantissa == 0 &&\\n actionPaused(address(vToken), Action.BORROW) &&\\n vToken.reserveFactorMantissa() == MANTISSA_ONE;\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n }\\n\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionPaused(\\n address market,\\n Action action,\\n bool paused\\n ) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(address account, function(VToken) internal view returns (Exp memory) weight)\\n internal\\n view\\n returns (AccountLiquiditySnapshot memory snapshot)\\n {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = accountAssets[account];\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(VToken vToken, address user)\\n internal\\n view\\n returns (\\n uint256 vTokenBalance,\\n uint256 borrowBalance,\\n uint256 exchangeRateMantissa\\n )\\n {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x73fdb4e4b2a2cfec75b0ef5a19491c4136a7953e1239989fb77ed26c1b7a77ac\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(\\n address vToken,\\n address minter,\\n uint256 mintAmount\\n ) external;\\n\\n function preRedeemHook(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) external;\\n\\n function preBorrowHook(\\n address vToken,\\n address borrower,\\n uint256 borrowAmount\\n ) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function preTransferHook(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x0ac4cc1e962946a665033bc50251c33ce59998e492d9f4a76cf0231bf0b0f545\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // Multiplier representing the most one can borrow against their collateral in this market.\\n // For instance, 0.9 to allow borrowing 90% of collateral value.\\n // Must be between 0 and 1, and stored as a mantissa.\\n uint256 collateralFactorMantissa;\\n // Multiplier representing the collateralization after which the borrow is eligible\\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n // value. Must be between 0 and collateral factor, stored as a mantissa.\\n uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\n enum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n }\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint256 public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n /**\\n * @notice Official mapping of vTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\\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\":\"0x23a035905b74bfbc8840b76690490a67b8861b2025f109fb5ac9fac13be909d3\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x3f8ec4e18bca1fdf8619966f4f6e095e205517a78f8c741b87fe82125754f96f\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(\\n Exp memory a,\\n uint256 scalar,\\n uint256 addend\\n ) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0xc13fcd089aa939e53b9c494c24beed316d572e9d433a44034eefa77915b673ec\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"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\"},\"contracts/Pool/PoolRegistryInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title PoolRegistryInterface\\n * @author Venus\\n * @notice Interface implemented by `PoolRegistry`.\\n */\\ninterface PoolRegistryInterface {\\n /**\\n * @notice Struct for a Venus interest rate pool.\\n */\\n struct VenusPool {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n }\\n\\n /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7e8ccd190ef019a3f8c3fcb67ed3eadd7bed32b263f88566870d138cd95ae312\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each block for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller private comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlock(address[],uint32[],uint32[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumber();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\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 */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumber = getBlockNumber();\\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n function getBlockNumber() public view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumber();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(\\n VToken vToken,\\n uint256 supplySpeed,\\n uint256 borrowSpeed\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplyIndex = supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowIndex = borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\\n blockNumber = supplyState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\\n\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n supplyState.index = safe224(\\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n supplyState.block = blockNumber;\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\\n blockNumber = borrowState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n borrowState.index = safe224(\\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n borrowState.block = blockNumber;\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0x0e5bede4edc4346e689de0adcf98dc9642feb55d44c1916715741c5937a34d52\",\"license\":\"BSD-3-Clause\"},\"contracts/RiskFund/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title IProtocolShareReserve\\n * @author Venus\\n * @notice Interface implemented by `ProtocolShareReserve`.\\n */\\ninterface IProtocolShareReserve {\\n function updateAssetsState(address comptroller, address asset) external;\\n}\\n\",\"keccak256\":\"0x45bf43fe09973ebfe0b5d3e81f966d7521b88c118d6ff64c289c500a62a7d564\",\"license\":\"BSD-3-Clause\"},\"contracts/RiskFund/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 swapPoolsAssets(\\n address[] calldata markets,\\n uint256[] calldata amountsOutMin,\\n address[][] calldata paths,\\n uint256 deadline\\n ) external returns (uint256);\\n\\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\\n\\n function updateAssetsState(address comptroller, address asset) external;\\n\\n function convertibleBaseAsset() external view returns (address);\\n\\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xa519791948d96fb81143cdd9db0a2b753a39f1f9ca4e8c68b92997e2095f241a\",\"license\":\"BSD-3-Clause\"},\"contracts/RiskFund/ProtocolShareReserve.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 { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\n\\nimport { IProtocolShareReserve } from \\\"./IProtocolShareReserve.sol\\\";\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { ReserveHelpers } from \\\"./ReserveHelpers.sol\\\";\\nimport { IRiskFund } from \\\"./IRiskFund.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\ncontract ProtocolShareReserve is ExponentialNoError, ReserveHelpers, IProtocolShareReserve {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n address public protocolIncome;\\n address public riskFund;\\n // Percentage of funds not sent to the RiskFund contract when the funds are released, following the project Tokenomics\\n uint256 private constant PROTOCOL_SHARE_PERCENTAGE = 50;\\n uint256 private constant BASE_UNIT = 100;\\n\\n /// @notice Emitted when funds are released\\n event FundsReleased(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice Emitted when pool registry address is updated\\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\\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 /**\\n * @notice Initializes the deployer to owner.\\n * @param protocolIncome_ The address protocol income will be sent to\\n * @param riskFund_ Risk fund address\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol income address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when risk fund address is zero\\n */\\n function initialize(address protocolIncome_, address riskFund_) external initializer {\\n ensureNonzeroAddress(protocolIncome_);\\n ensureNonzeroAddress(riskFund_);\\n\\n __Ownable2Step_init();\\n\\n protocolIncome = protocolIncome_;\\n riskFund = riskFund_;\\n }\\n\\n /**\\n * @notice 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 address oldPoolRegistry = poolRegistry;\\n poolRegistry = poolRegistry_;\\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\\n }\\n\\n /**\\n * @notice Release funds\\n * @param comptroller Pool's Comptroller\\n * @param asset Asset to be released\\n * @param amount Amount to release\\n * @return Number of total released tokens\\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\\n */\\n function releaseFunds(\\n address comptroller,\\n address asset,\\n uint256 amount\\n ) external nonReentrant returns (uint256) {\\n ensureNonzeroAddress(asset);\\n require(amount <= _poolsAssetsReserves[comptroller][asset], \\\"ProtocolShareReserve: Insufficient pool balance\\\");\\n\\n assetsReserves[asset] -= amount;\\n _poolsAssetsReserves[comptroller][asset] -= amount;\\n uint256 protocolIncomeAmount = mul_(\\n Exp({ mantissa: amount }),\\n div_(Exp({ mantissa: PROTOCOL_SHARE_PERCENTAGE * EXP_SCALE }), BASE_UNIT)\\n ).mantissa;\\n\\n address riskFund_ = riskFund;\\n\\n emit FundsReleased(comptroller, asset, amount);\\n\\n IERC20Upgradeable(asset).safeTransfer(protocolIncome, protocolIncomeAmount);\\n IERC20Upgradeable(asset).safeTransfer(riskFund_, amount - protocolIncomeAmount);\\n\\n // Update the pool asset's state in the risk fund for the above transfer.\\n IRiskFund(riskFund_).updateAssetsState(comptroller, asset);\\n\\n return amount;\\n }\\n\\n /**\\n * @notice 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 */\\n function updateAssetsState(address comptroller, address asset)\\n public\\n override(IProtocolShareReserve, ReserveHelpers)\\n {\\n super.updateAssetsState(comptroller, asset);\\n }\\n}\\n\",\"keccak256\":\"0x871a26ce46666f37ff88034dec23d0bb9497b057a861bfd35b166a3ea3e4c785\",\"license\":\"BSD-3-Clause\"},\"contracts/RiskFund/ReserveHelpers.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\n\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\nimport { ComptrollerInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\n\\ncontract ReserveHelpers is Ownable2StepUpgradeable {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 private constant NOT_ENTERED = 1;\\n\\n uint256 private constant ENTERED = 2;\\n\\n // Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools).\\n mapping(address => uint256) public assetsReserves;\\n\\n // Store the asset's reserve per pool in the ProtocolShareReserve.\\n // Comptroller(pool) -> Asset -> amount\\n mapping(address => mapping(address => uint256)) internal _poolsAssetsReserves;\\n\\n // Address of pool registry contract\\n address public poolRegistry;\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n uint256 internal status;\\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 */\\n uint256[46] private __gap;\\n\\n /// @notice Event emitted after the update of the assets reserves.\\n /// @param comptroller Pool's Comptroller address\\n /// @param asset Token address\\n /// @param amount An amount by which the reserves have increased\\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\\n\\n /// @notice event emitted on sweep token success\\n event SweepToken(address indexed token, address indexed to, uint256 amount);\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(status != ENTERED, \\\"re-entered\\\");\\n status = ENTERED;\\n _;\\n status = NOT_ENTERED;\\n }\\n\\n /**\\n * @notice A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input\\n * @param _token The address of the BEP-20 token to sweep\\n * @param _to Recipient of the output tokens.\\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\\n * @custom:access Only Owner\\n */\\n function sweepToken(address _token, address _to) external onlyOwner nonReentrant {\\n ensureNonzeroAddress(_to);\\n uint256 balanceDfference_;\\n uint256 balance_ = IERC20Upgradeable(_token).balanceOf(address(this));\\n\\n require(balance_ > assetsReserves[_token], \\\"ReserveHelpers: Zero surplus tokens\\\");\\n unchecked {\\n balanceDfference_ = balance_ - assetsReserves[_token];\\n }\\n\\n emit SweepToken(_token, _to, balanceDfference_);\\n IERC20Upgradeable(_token).safeTransfer(_to, balanceDfference_);\\n }\\n\\n /**\\n * @notice 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 Asset's reserve in risk fund.\\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\\n */\\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256) {\\n ensureNonzeroAddress(asset);\\n require(ComptrollerInterface(comptroller).isComptroller(), \\\"ReserveHelpers: Comptroller address invalid\\\");\\n return _poolsAssetsReserves[comptroller][asset];\\n }\\n\\n /**\\n * @notice 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 * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\\n */\\n function updateAssetsState(address comptroller, address asset) public virtual {\\n ensureNonzeroAddress(asset);\\n require(ComptrollerInterface(comptroller).isComptroller(), \\\"ReserveHelpers: Comptroller address invalid\\\");\\n address poolRegistry_ = poolRegistry;\\n require(poolRegistry_ != address(0), \\\"ReserveHelpers: Pool Registry address is not set\\\");\\n require(\\n PoolRegistryInterface(poolRegistry_).getVTokenForAsset(comptroller, asset) != address(0),\\n \\\"ReserveHelpers: The pool doesn't support the asset\\\"\\n );\\n\\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\\n uint256 assetReserve = assetsReserves[asset];\\n if (currentBalance > assetReserve) {\\n uint256 balanceDifference;\\n unchecked {\\n balanceDifference = currentBalance - assetReserve;\\n }\\n assetsReserves[asset] += balanceDifference;\\n _poolsAssetsReserves[comptroller][asset] += balanceDifference;\\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x689e7d9481b9a86b421de41ad87459e92146c5f2e00ac041b853ee3ad14e4bdf\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { IProtocolShareReserve } from \\\"./RiskFund/IProtocolShareReserve.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\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 /**\\n * @notice Construct a new money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\n );\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n _borrowFresh(msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return amount The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(address account)\\n external\\n view\\n override\\n returns (\\n uint256 error,\\n uint256 vTokenBalance,\\n uint256 borrowBalance,\\n uint256 exchangeRate\\n )\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return rate The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this v\\n * @return rate The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage.\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number */\\n uint256 currentBlockNumber = _getBlockNumber();\\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is sending the assets for supply\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n */\\n function _mintFresh(\\n address payer,\\n address minter,\\n uint256 mintAmount\\n ) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `_doTransferIn` for the minter and the mintAmount.\\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n }\\n\\n /**\\n * @notice User redeems vTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n */\\n function _redeemFresh(\\n address redeemer,\\n uint256 redeemTokensIn,\\n uint256 redeemAmountIn\\n ) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\\n * On success, the vToken has redeemAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(redeemer, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrower User who borrows the assets\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the borrower and the borrowAmount.\\n * On success, the vToken borrowAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(borrower, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call _doTransferIn for the payer and the repayAmount\\n * On success, the vToken holds an additional repayAmount of cash.\\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == NO_ERROR, \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n */\\n function _seize(\\n address seizerContract,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n uint256 totalReservesNew = totalReserves + protocolSeizeAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalReserves = totalReservesNew;\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit Transfer(borrower, address(this), protocolSeizeTokens);\\n emit ReservesAdded(address(this), protocolSeizeAmount, totalReservesNew);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(address(comptroller), underlying);\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetInterestRateModelFreshCheck();\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\\n * This function returns the actual amount received,\\n * which may be less than `amount` if there is a fee attached to the transfer.\\n * @param from Sender of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n * @return Actual amount received\\n */\\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n // Return the amount that was *actually* transferred\\n return balanceAfter - balanceBefore;\\n }\\n\\n /**\\n * @dev Just a regular ERC-20 transfer, reverts on failure\\n * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n */\\n function _transferTokens(\\n address spender,\\n address src,\\n address dst,\\n uint256 tokens\\n ) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n _setComptroller(comptroller_);\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = _getBlockNumber();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying tokens owned by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n return token.balanceOf(address(this));\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n * @return Current block number\\n */\\n function _getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0x90ec54cadfdd13bc09a1bc4ae1cc37585b695804a6c95d8b42fb866ec269a300\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\n\\n // Maximum borrow rate that can ever be applied (.0005% / block)\\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\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\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address indexed admin, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 amount\\n ) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account)\\n external\\n view\\n virtual\\n returns (\\n uint256,\\n uint256,\\n uint256,\\n uint256\\n );\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xe82d0de552cfda8da11191a3b0bd24d5e218f182d1fdb776585b97cf27c5f4de\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/// @dev The approximate number of blocks per year that is assumed by the interest rate model\\nuint256 constant BLOCKS_PER_YEAR = 10_512_000;\\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\",\"keccak256\":\"0x04cd899695ea593a2529cb6a1a04c2a34bff0c1516bd70a5f638ae7a850cad8b\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x909eb76841ebd57d8f53686b76b1a09da7bbbbcddb29510c41674d5aa84c713e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061001961001e565b6100dd565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146100db576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611480806100ec6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80637b77cd6a11610097578063aac59a7511610066578063aac59a75146101ed578063afcff50f14610200578063e30c397814610213578063f2fde38b1461022457600080fd5b80637b77cd6a146101a35780637cf89030146101b65780638bbdf2af146101c95780638da5cb5b146101dc57600080fd5b8063485cc955116100d3578063485cc9551461016d5780636fb0527514610180578063715018a61461019357806379ba50971461019b57600080fd5b80630e3e3e3a146100fa578063258836fe1461012a578063439b55171461013f575b600080fd5b60c95461010d906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61013d6101383660046111c0565b610237565b005b61015f61014d3660046111f9565b60976020526000908152604090205481565b604051908152602001610121565b61013d61017b3660046111c0565b6103ea565b61015f61018e3660046111c0565b61053f565b61013d6105f3565b61013d610607565b61013d6101b13660046111f9565b610681565b60ca5461010d906001600160a01b031681565b61015f6101d7366004611216565b6106e4565b6033546001600160a01b031661010d565b61013d6101fb3660046111c0565b610968565b60995461010d906001600160a01b031681565b6065546001600160a01b031661010d565b61013d6102323660046111f9565b610976565b61023f6109e7565b6002609a54036102835760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b60448201526064015b60405180910390fd5b6002609a5561029181610a41565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156102da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102fe9190611257565b6001600160a01b03851660009081526097602052604090205490915081116103745760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b606482015260840161027a565b6001600160a01b038481166000818152609760209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36103df6001600160a01b0385168484610a68565b50506001609a555050565b600054610100900460ff161580801561040a5750600054600160ff909116105b806104245750303b158015610424575060005460ff166001145b6104875760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161027a565b6000805460ff1916600117905580156104aa576000805461ff0019166101001790555b6104b383610a41565b6104bc82610a41565b6104c4610aba565b60c980546001600160a01b038086166001600160a01b03199283161790925560ca805492851692909116919091179055801561053a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600061054a82610a41565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab9190611270565b6105c75760405162461bcd60e51b815260040161027a90611292565b506001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b6105fb6109e7565b6106056000610ae9565b565b60655433906001600160a01b031681146106755760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161027a565b61067e81610ae9565b50565b6106896109e7565b61069281610a41565b609980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b60006002609a54036107255760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015260640161027a565b6002609a5561073383610a41565b6001600160a01b038085166000908152609860209081526040808320938716835292905220548211156107c05760405162461bcd60e51b815260206004820152602f60248201527f50726f746f636f6c5368617265526573657276653a20496e737566666963696560448201526e6e7420706f6f6c2062616c616e636560881b606482015260840161027a565b6001600160a01b038316600090815260976020526040812080548492906107e89084906112f3565b90915550506001600160a01b038085166000908152609860209081526040808320938716835292905290812080548492906108249084906112f3565b92505081905550600061087060405180602001604052808581525061086b6040518060200160405280670de0b6b3a76400006032610862919061130a565b90526064610b02565b610b33565b5160ca546040518581529192506001600160a01b0390811691868216918816907feed10c470424824e4a4309075162f10b9989088b23fbed2349698cedd44493fb9060200160405180910390a360c9546108d7906001600160a01b03878116911684610a68565b6108f6816108e584876112f3565b6001600160a01b0388169190610a68565b60405163aac59a7560e01b81526001600160a01b038781166004830152868116602483015282169063aac59a7590604401600060405180830381600087803b15801561094157600080fd5b505af1158015610955573d6000803e3d6000fd5b50506001609a5550939695505050505050565b6109728282610b72565b5050565b61097e6109e7565b606580546001600160a01b0383166001600160a01b031990911681179091556109af6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146106055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161027a565b6001600160a01b03811661067e576040516342bcdf7f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261053a908490610ea5565b600054610100900460ff16610ae15760405162461bcd60e51b815260040161027a90611329565b610605610f7a565b606580546001600160a01b031916905561067e81610faa565b6040805160208101909152600081526040518060200160405280610b2a856000015185610ffc565b90529392505050565b6040805160208101909152600081526040518060200160405280670de0b6b3a7640000610b688660000151866000015161100f565b610b2a9190611374565b610b7b81610a41565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdc9190611270565b610bf85760405162461bcd60e51b815260040161027a90611292565b6099546001600160a01b031680610c6a5760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b606482015260840161027a565b60405163266e0a7f60e01b81526001600160a01b03848116600483015283811660248301526000919083169063266e0a7f90604401602060405180830381865afa158015610cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce09190611396565b6001600160a01b031603610d515760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b606482015260840161027a565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbc9190611257565b6001600160a01b03841660009081526097602052604090205490915080821115610e9e576001600160a01b0384166000908152609760205260408120805483850392839291610e0c9084906113b3565b90915550506001600160a01b03808716600090815260986020908152604080832093891683529290529081208054839290610e489084906113b3565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce3883604051610e9491815260200190565b60405180910390a3505b5050505050565b6000610efa826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661101b9092919063ffffffff16565b9050805160001480610f1b575080806020019051810190610f1b9190611270565b61053a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161027a565b600054610100900460ff16610fa15760405162461bcd60e51b815260040161027a90611329565b61060533610ae9565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006110088284611374565b9392505050565b6000611008828461130a565b606061102a8484600085611032565b949350505050565b6060824710156110935760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161027a565b600080866001600160a01b031685876040516110af91906113fb565b60006040518083038185875af1925050503d80600081146110ec576040519150601f19603f3d011682016040523d82523d6000602084013e6110f1565b606091505b50915091506111028783838761110d565b979650505050505050565b6060831561117c578251600003611175576001600160a01b0385163b6111755760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161027a565b508161102a565b61102a83838151156111915781518083602001fd5b8060405162461bcd60e51b815260040161027a9190611417565b6001600160a01b038116811461067e57600080fd5b600080604083850312156111d357600080fd5b82356111de816111ab565b915060208301356111ee816111ab565b809150509250929050565b60006020828403121561120b57600080fd5b8135611008816111ab565b60008060006060848603121561122b57600080fd5b8335611236816111ab565b92506020840135611246816111ab565b929592945050506040919091013590565b60006020828403121561126957600080fd5b5051919050565b60006020828403121561128257600080fd5b8151801515811461100857600080fd5b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082821015611305576113056112dd565b500390565b6000816000190483118215151615611324576113246112dd565b500290565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008261139157634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156113a857600080fd5b8151611008816111ab565b600082198211156113c6576113c66112dd565b500190565b60005b838110156113e65781810151838201526020016113ce565b838111156113f5576000848401525b50505050565b6000825161140d8184602087016113cb565b9190910192915050565b60208152600082518060208401526114368160408501602087016113cb565b601f01601f1916919091016040019291505056fea26469706673582212203e243cb1b5d00b5ce8fca153bc592828d0668926156305aabe1b7e91490ff94664736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c80637b77cd6a11610097578063aac59a7511610066578063aac59a75146101ed578063afcff50f14610200578063e30c397814610213578063f2fde38b1461022457600080fd5b80637b77cd6a146101a35780637cf89030146101b65780638bbdf2af146101c95780638da5cb5b146101dc57600080fd5b8063485cc955116100d3578063485cc9551461016d5780636fb0527514610180578063715018a61461019357806379ba50971461019b57600080fd5b80630e3e3e3a146100fa578063258836fe1461012a578063439b55171461013f575b600080fd5b60c95461010d906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61013d6101383660046111c0565b610237565b005b61015f61014d3660046111f9565b60976020526000908152604090205481565b604051908152602001610121565b61013d61017b3660046111c0565b6103ea565b61015f61018e3660046111c0565b61053f565b61013d6105f3565b61013d610607565b61013d6101b13660046111f9565b610681565b60ca5461010d906001600160a01b031681565b61015f6101d7366004611216565b6106e4565b6033546001600160a01b031661010d565b61013d6101fb3660046111c0565b610968565b60995461010d906001600160a01b031681565b6065546001600160a01b031661010d565b61013d6102323660046111f9565b610976565b61023f6109e7565b6002609a54036102835760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b60448201526064015b60405180910390fd5b6002609a5561029181610a41565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156102da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102fe9190611257565b6001600160a01b03851660009081526097602052604090205490915081116103745760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b606482015260840161027a565b6001600160a01b038481166000818152609760209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36103df6001600160a01b0385168484610a68565b50506001609a555050565b600054610100900460ff161580801561040a5750600054600160ff909116105b806104245750303b158015610424575060005460ff166001145b6104875760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161027a565b6000805460ff1916600117905580156104aa576000805461ff0019166101001790555b6104b383610a41565b6104bc82610a41565b6104c4610aba565b60c980546001600160a01b038086166001600160a01b03199283161790925560ca805492851692909116919091179055801561053a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600061054a82610a41565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ab9190611270565b6105c75760405162461bcd60e51b815260040161027a90611292565b506001600160a01b03918216600090815260986020908152604080832093909416825291909152205490565b6105fb6109e7565b6106056000610ae9565b565b60655433906001600160a01b031681146106755760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161027a565b61067e81610ae9565b50565b6106896109e7565b61069281610a41565b609980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b60006002609a54036107255760405162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015260640161027a565b6002609a5561073383610a41565b6001600160a01b038085166000908152609860209081526040808320938716835292905220548211156107c05760405162461bcd60e51b815260206004820152602f60248201527f50726f746f636f6c5368617265526573657276653a20496e737566666963696560448201526e6e7420706f6f6c2062616c616e636560881b606482015260840161027a565b6001600160a01b038316600090815260976020526040812080548492906107e89084906112f3565b90915550506001600160a01b038085166000908152609860209081526040808320938716835292905290812080548492906108249084906112f3565b92505081905550600061087060405180602001604052808581525061086b6040518060200160405280670de0b6b3a76400006032610862919061130a565b90526064610b02565b610b33565b5160ca546040518581529192506001600160a01b0390811691868216918816907feed10c470424824e4a4309075162f10b9989088b23fbed2349698cedd44493fb9060200160405180910390a360c9546108d7906001600160a01b03878116911684610a68565b6108f6816108e584876112f3565b6001600160a01b0388169190610a68565b60405163aac59a7560e01b81526001600160a01b038781166004830152868116602483015282169063aac59a7590604401600060405180830381600087803b15801561094157600080fd5b505af1158015610955573d6000803e3d6000fd5b50506001609a5550939695505050505050565b6109728282610b72565b5050565b61097e6109e7565b606580546001600160a01b0383166001600160a01b031990911681179091556109af6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b031633146106055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161027a565b6001600160a01b03811661067e576040516342bcdf7f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261053a908490610ea5565b600054610100900460ff16610ae15760405162461bcd60e51b815260040161027a90611329565b610605610f7a565b606580546001600160a01b031916905561067e81610faa565b6040805160208101909152600081526040518060200160405280610b2a856000015185610ffc565b90529392505050565b6040805160208101909152600081526040518060200160405280670de0b6b3a7640000610b688660000151866000015161100f565b610b2a9190611374565b610b7b81610a41565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdc9190611270565b610bf85760405162461bcd60e51b815260040161027a90611292565b6099546001600160a01b031680610c6a5760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b606482015260840161027a565b60405163266e0a7f60e01b81526001600160a01b03848116600483015283811660248301526000919083169063266e0a7f90604401602060405180830381865afa158015610cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce09190611396565b6001600160a01b031603610d515760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b606482015260840161027a565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610d98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbc9190611257565b6001600160a01b03841660009081526097602052604090205490915080821115610e9e576001600160a01b0384166000908152609760205260408120805483850392839291610e0c9084906113b3565b90915550506001600160a01b03808716600090815260986020908152604080832093891683529290529081208054839290610e489084906113b3565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce3883604051610e9491815260200190565b60405180910390a3505b5050505050565b6000610efa826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661101b9092919063ffffffff16565b9050805160001480610f1b575080806020019051810190610f1b9190611270565b61053a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161027a565b600054610100900460ff16610fa15760405162461bcd60e51b815260040161027a90611329565b61060533610ae9565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006110088284611374565b9392505050565b6000611008828461130a565b606061102a8484600085611032565b949350505050565b6060824710156110935760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161027a565b600080866001600160a01b031685876040516110af91906113fb565b60006040518083038185875af1925050503d80600081146110ec576040519150601f19603f3d011682016040523d82523d6000602084013e6110f1565b606091505b50915091506111028783838761110d565b979650505050505050565b6060831561117c578251600003611175576001600160a01b0385163b6111755760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161027a565b508161102a565b61102a83838151156111915781518083602001fd5b8060405162461bcd60e51b815260040161027a9190611417565b6001600160a01b038116811461067e57600080fd5b600080604083850312156111d357600080fd5b82356111de816111ab565b915060208301356111ee816111ab565b809150509250929050565b60006020828403121561120b57600080fd5b8135611008816111ab565b60008060006060848603121561122b57600080fd5b8335611236816111ab565b92506020840135611246816111ab565b929592945050506040919091013590565b60006020828403121561126957600080fd5b5051919050565b60006020828403121561128257600080fd5b8151801515811461100857600080fd5b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082821015611305576113056112dd565b500390565b6000816000190483118215151615611324576113246112dd565b500290565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008261139157634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156113a857600080fd5b8151611008816111ab565b600082198211156113c6576113c66112dd565b500190565b60005b838110156113e65781810151838201526020016113ce565b838111156113f5576000848401525b50505050565b6000825161140d8184602087016113cb565b9190910192915050565b60208152600082518060208401526114368160408501602087016113cb565b601f01601f1916919091016040019291505056fea26469706673582212203e243cb1b5d00b5ce8fca153bc592828d0668926156305aabe1b7e91490ff94664736f6c634300080d0033", - "devdoc": { - "kind": "dev", - "methods": { - "acceptOwnership()": { - "details": "The new owner accepts the ownership transfer." - }, - "constructor": { - "custom:oz-upgrades-unsafe-allow": "constructor" - }, - "getPoolAssetReserve(address,address)": { - "custom:error": "ZeroAddressNotAllowed is thrown when asset address is zero", - "params": { - "asset": "Asset address.", - "comptroller": "Comptroller address(pool)." - }, - "returns": { - "_0": "Asset's reserve in risk fund." - } - }, - "initialize(address,address)": { - "custom:error": "ZeroAddressNotAllowed is thrown when protocol income address is zeroZeroAddressNotAllowed is thrown when risk fund address is zero", - "params": { - "protocolIncome_": "The address protocol income will be sent to", - "riskFund_": "Risk fund address" - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "pendingOwner()": { - "details": "Returns the address of the pending owner." - }, - "releaseFunds(address,address,uint256)": { - "custom:error": "ZeroAddressNotAllowed is thrown when asset address is zero", - "params": { - "amount": "Amount to release", - "asset": "Asset to be released", - "comptroller": "Pool's Comptroller" - }, - "returns": { - "_0": "Number of total released tokens" - } - }, - "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." - }, - "setPoolRegistry(address)": { - "custom:error": "ZeroAddressNotAllowed is thrown when pool registry address is zero", - "params": { - "poolRegistry_": "Address of the pool registry" - } - }, - "sweepToken(address,address)": { - "custom:access": "Only Owner", - "custom:error": "ZeroAddressNotAllowed is thrown when asset address is zero", - "params": { - "_to": "Recipient of the output tokens.", - "_token": "The address of the BEP-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)": { - "params": { - "asset": "Asset address.", - "comptroller": "Comptroller address(pool)" - } - } - }, - "version": 1 - }, - "userdoc": { - "errors": { - "ZeroAddressNotAllowed()": [ - { - "notice": "Thrown if the supplied address is a zero address where it is not allowed" - } - ] - }, - "events": { - "AssetsReservesUpdated(address,address,uint256)": { - "notice": "Event emitted after the update of the assets reserves." - }, - "FundsReleased(address,address,uint256)": { - "notice": "Emitted when funds are released" - }, - "PoolRegistryUpdated(address,address)": { - "notice": "Emitted when pool registry address is updated" - }, - "SweepToken(address,address,uint256)": { - "notice": "event emitted on sweep token success" - } - }, - "kind": "user", - "methods": { - "getPoolAssetReserve(address,address)": { - "notice": "Get the Amount of the asset in the risk fund for the specific pool." - }, - "initialize(address,address)": { - "notice": "Initializes the deployer to owner." - }, - "releaseFunds(address,address,uint256)": { - "notice": "Release funds" - }, - "setPoolRegistry(address)": { - "notice": "Pool registry setter." - }, - "sweepToken(address,address)": { - "notice": "A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input" - }, - "updateAssetsState(address,address)": { - "notice": "Update the reserve of the asset for the specific pool after transferring to the protocol share reserve." - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 290, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 293, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 1397, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 162, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 282, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 71, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_pendingOwner", - "offset": 0, - "slot": "101", - "type": "t_address" - }, - { - "astId": 150, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "__gap", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 13338, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "assetsReserves", - "offset": 0, - "slot": "151", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 13344, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "_poolsAssetsReserves", - "offset": 0, - "slot": "152", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 13346, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "poolRegistry", - "offset": 0, - "slot": "153", - "type": "t_address" - }, - { - "astId": 13349, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "status", - "offset": 0, - "slot": "154", - "type": "t_uint256" - }, - { - "astId": 13354, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "__gap", - "offset": 0, - "slot": "155", - "type": "t_array(t_uint256)46_storage" - }, - { - "astId": 13101, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "protocolIncome", - "offset": 0, - "slot": "201", - "type": "t_address" - }, - { - "astId": 13103, - "contract": "contracts/RiskFund/ProtocolShareReserve.sol:ProtocolShareReserve", - "label": "riskFund", - "offset": 0, - "slot": "202", - "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_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/RewardsDistributor_DeFi_2.json b/deployments/bsctestnet/RewardsDistributor_DeFi_2.json new file mode 100644 index 000000000..fe45d9c51 --- /dev/null +++ b/deployments/bsctestnet/RewardsDistributor_DeFi_2.json @@ -0,0 +1,1270 @@ +{ + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "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": [ + { + "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": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAccrued", + "type": "uint256" + } + ], + "name": "ContributorRewardsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketInitialized", + "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": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "RewardTokenBorrowIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardTokenGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "RewardTokenSupplyIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenSupplySpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "SupplyLastRewardingBlockUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "INITIAL_INDEX", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "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": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "distributeBorrowerRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", + "type": "address" + } + ], + "name": "distributeSupplierRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "grantRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract Comptroller", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "initializeMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastContributorBlock", + "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": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenContributorSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardTokenSpeed", + "type": "uint256" + } + ], + "name": "setContributorRewardTokenSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" + } + ], + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "setRewardTokenSpeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + } + ], + "name": "updateContributorRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updateRewardTokenSupplyIndex", + "outputs": [], + "stateMutability": "nonpayable", + "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": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "receipt": { + "to": null, + "from": "0x03862dFa5D0be8F64509C001cb8C6188194469DF", + "contractAddress": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "transactionIndex": 0, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000000000100000000000000000000000000000000008000000000000000000000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000000001000000000000080000000008000800000000000001000000002002000000400000000000000800000000000000000000000000020000000000000000201040000000000000400000000400000000020000000000200000000000000000000000000000800000000000000000000800001", + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880", + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000fae44cf6309598c2557bb265bf0401d594db97da" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" + }, + { + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000003862dfa5d0be8f64509c001cb8c6188194469df" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" + }, + { + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 2, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" + }, + { + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 3, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" + }, + { + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 4, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" + }, + { + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007877ffd62649b6a1557b55d4c20fcbab17344c91", + "logIndex": 5, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" + } + ], + "blockNumber": 34736974, + "cumulativeGasUsed": "865817", + "status": 1, + "byzantium": true + }, + "args": [ + "0xfAE44cf6309598c2557Bb265BF0401D594db97DA", + "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", + "0xbe20309400000000000000000000000023a73971a6b9f6580c048b9cb188869b2a2aa2ad000000000000000000000000a11c8d9dc9b66e209ef60f0c8d969d3cd988782c000000000000000000000000000000000000000000000000000000000000006400000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa" + ], + "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": [ + "0x23a73971A6B9f6580c048B9CB188869B2A2aA2aD", + "0xA11c8D9DC9b66E209Ef60F0C8D969D3CD988782c", + 100, + "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA" + ] + }, + "implementation": "0xfAE44cf6309598c2557Bb265BF0401D594db97DA", + "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/ProtocolShareReserve.json b/deployments/bsctestnet/RewardsDistributor_DeFi_2_Proxy.json similarity index 84% rename from deployments/bsctestnet/ProtocolShareReserve.json rename to deployments/bsctestnet/RewardsDistributor_DeFi_2_Proxy.json index 0c99fe840..03ae90f04 100644 --- a/deployments/bsctestnet/ProtocolShareReserve.json +++ b/deployments/bsctestnet/RewardsDistributor_DeFi_2_Proxy.json @@ -1,6 +1,27 @@ { - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", "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": [ @@ -123,489 +144,102 @@ { "stateMutability": "payable", "type": "receive" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "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": "comptroller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsReleased", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "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": "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": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "assetsReserves", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "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": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "protocolIncome_", - "type": "address" - }, - { - "internalType": "address", - "name": "riskFund_", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "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": [], - "name": "protocolIncome", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "releaseFunds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "riskFund", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "poolRegistry_", - "type": "address" - } - ], - "name": "setPoolRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "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" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_logic", - "type": "address" - }, - { - "internalType": "address", - "name": "admin_", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" } ], - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", "receipt": { "to": null, - "from": "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706", - "contractAddress": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", - "transactionIndex": 1, - "gasUsed": "817670", - "logsBloom": "0x10000000000000000000000000000000400000040000000000800008000000000000000000000040000000000000000000000000000001000000000000004000000000000000000000000000000002000001000000001000000000000000000000000008020000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000000000080000000000000800000000000000000000000000000000400000000000000000000000000000000004000000020000000000000000000040000000000000400000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943", - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", + "from": "0x03862dFa5D0be8F64509C001cb8C6188194469DF", + "contractAddress": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "transactionIndex": 0, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000000000100000000000000000000000000000000008000000000000000000000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000000000000001000000000000080000000008000800000000000001000000002002000000400000000000000800000000000000000000000000020000000000000000201040000000000000400000000400000000020000000000200000000000000000000000000000800000000000000000000800001", + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880", + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", "logs": [ { - "transactionIndex": 1, - "blockNumber": 33267957, - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", - "0x0000000000000000000000000bbea4b14f475bf5eb60fc2b0ca90d3d089ef833" + "0x000000000000000000000000fae44cf6309598c2557bb265bf0401d594db97da" ], "data": "0x", "logIndex": 0, - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943" + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" }, { - "transactionIndex": 1, - "blockNumber": 33267957, - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000002ce1d0ffd7e869d9df33e28552b12ddded326706" + "0x00000000000000000000000003862dfa5d0be8f64509c001cb8c6188194469df" ], "data": "0x", "logIndex": 1, - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943" + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" + }, + { + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 2, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" + }, + { + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 3, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" }, { - "transactionIndex": 1, - "blockNumber": 33267957, - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 2, - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943" + "logIndex": 4, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" }, { - "transactionIndex": 1, - "blockNumber": 33267957, - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "transactionIndex": 0, + "blockNumber": 34736974, + "transactionHash": "0x4c74e2345295999f4354b20a26a936ee1f59e2922dc9f99a15ca2db0e32fef51", + "address": "0x9372F0d88988B2cC0a2bf8700a5B3f04B0b81b8C", "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007877ffd62649b6a1557b55d4c20fcbab17344c91", - "logIndex": 3, - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943" + "logIndex": 5, + "blockHash": "0x2c94164080bebe832088c2beddcc388cd3f7da9359be26ab84226c0b8ad2d880" } ], - "blockNumber": 33267957, - "cumulativeGasUsed": "848911", + "blockNumber": 34736974, + "cumulativeGasUsed": "865817", "status": 1, "byzantium": true }, "args": [ - "0x0Bbea4B14f475bF5eb60Fc2b0Ca90d3d089Ef833", + "0xfAE44cf6309598c2557Bb265BF0401D594db97DA", "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", - "0x485cc9550000000000000000000000008b293600c50d6fbdc6ed4251cc75ece29880276f000000000000000000000000487cef72dacabd7e12e633bb3b63815a386f7012" + "0xbe20309400000000000000000000000023a73971a6b9f6580c048b9cb188869b2a2aa2ad000000000000000000000000a11c8d9dc9b66e209ef60f0c8d969d3cd988782c000000000000000000000000000000000000000000000000000000000000006400000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa" ], "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": ["0x8b293600C50D6fbdc6Ed4251cc75ECe29880276f", "0x487CeF72dacABD7E12e633bb3B63815a386f7012"] - }, - "implementation": "0x0Bbea4B14f475bF5eb60Fc2b0Ca90d3d089Ef833", "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", diff --git a/deployments/bsctestnet/VToken_vPLANET_DeFi.json b/deployments/bsctestnet/VToken_vPLANET_DeFi.json new file mode 100644 index 000000000..a81cf6676 --- /dev/null +++ b/deployments/bsctestnet/VToken_vPLANET_DeFi.json @@ -0,0 +1,246 @@ +{ + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "receipt": { + "to": null, + "from": "0x03862dFa5D0be8F64509C001cb8C6188194469DF", + "contractAddress": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "transactionIndex": 0, + "gasUsed": "676025", + "logsBloom": "0x0000000000042000000000400000008008000000000000000080000000000000000000000000004000010002000000000000000000000000000000082000800000100000000000000000000000100000000100008000000000000000000000200000002002000000008000000000080020000400000000000000000000000040000000000002000080000000000008040000000000008010000a000000000000000000001000000100000000000500000000000000800000000000000000004000000044000000000002000200040000000000000000100000c00000000020000000000000000000008000800000040400000800000000000000004000010000", + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5", + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000006f48cf8e94562b5c37be1d0b6c50c845118cc498" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + }, + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000003862dfa5d0be8f64509c001cb8c6188194469df" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + }, + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 2, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + }, + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000023a73971a6b9f6580c048b9cb188869b2a2aa2ad" + ], + "data": "0x", + "logIndex": 3, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + }, + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000b7c5a751cca00b11af3ca4a35e9e992f0f9c9c9c" + ], + "data": "0x", + "logIndex": 4, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + }, + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003782dace9d90000", + "logIndex": 5, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + }, + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000503574a82fe2a9f968d355c8aac1ba0481859369" + ], + "data": "0x", + "logIndex": 6, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + }, + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000025c7c7d6bf710949fd7f03364e9ba19a1b3c10e3" + ], + "data": "0x", + "logIndex": 7, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + }, + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x00000000000000000000000003862dfa5d0be8f64509c001cb8c6188194469df", + "0x000000000000000000000000ce10739590001705f7ff231611ba4a48b2820327" + ], + "data": "0x", + "logIndex": 8, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + }, + { + "transactionIndex": 0, + "blockNumber": 34764734, + "transactionHash": "0xdaf45d5403bde9cd96a4f779990fbceef0400f50512071893b04128096ebc004", + "address": "0xe237aA131E7B004aC88CB808Fa56AF3dc4C408f1", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 9, + "blockHash": "0x698676efc0ee4b60ee6b970d6735d5bc2b76d09c575f2dd3228d3d36a916f6f5" + } + ], + "blockNumber": 34764734, + "cumulativeGasUsed": "676025", + "status": 1, + "byzantium": true + }, + "args": [ + "0x6F48cF8e94562b5C37be1D0B6C50C845118cc498", + "0x8a42c31900000000000000000000000052b4e1a2ba407813f829b4b3943a1e57768669a900000000000000000000000023a73971a6b9f6580c048b9cb188869b2a2aa2ad000000000000000000000000b7c5a751cca00b11af3ca4a35e9e992f0f9c9c9c0000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000ce10739590001705f7ff231611ba4a48b282032700000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa000000000000000000000000503574a82fe2a9f968d355c8aac1ba048185936900000000000000000000000025c7c7d6bf710949fd7f03364e9ba19a1b3c10e300000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000001356656e757320504c414e45542028446546692900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c76504c414e45545f446546690000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "82cd33260a9b17bbce6d70381b9dc2d8", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/bsctestnet/solcInputs/82cd33260a9b17bbce6d70381b9dc2d8.json b/deployments/bsctestnet/solcInputs/82cd33260a9b17bbce6d70381b9dc2d8.json new file mode 100644 index 000000000..59c9a9b96 --- /dev/null +++ b/deployments/bsctestnet/solcInputs/82cd33260a9b17bbce6d70381b9dc2d8.json @@ -0,0 +1,300 @@ +{ + "language": "Solidity", + "sources": { + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "@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/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.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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 Venus Access Control Contract.\n * @dev The AccessControlledV8 contract is a wrapper around the OpenZeppelin AccessControl contract\n * It provides a standardized way to control access to methods within the Venus Smart Contract Ecosystem.\n * The contract allows the owner to set an AccessControlManager contract address.\n * It can restrict method calls based on the sender's role and the method's signature.\n */\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/AccessControlManager.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title Venus Access Control Contract\n * @author venus\n * @dev This contract is a wrapper of OpenZeppelin AccessControl\n *\t\textending it in a way to standartize access control\n *\t\twithin Venus Smart Contract Ecosystem\n */\ncontract AccessControlManager is AccessControl, IAccessControlManagerV8 {\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(address contractAddress, string calldata functionSig, address accountToPermit) 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 calldata 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 calldata 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 calldata functionSig\n ) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n return hasRole(role, account);\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\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/FeedRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface FeedRegistryInterface {\n function latestRoundDataByName(\n string memory base,\n string memory quote\n )\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n function decimalsByName(string memory base, string memory quote) external view returns (uint8);\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/PublicResolverInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\ninterface PublicResolverInterface {\n function addr(bytes32 node) external view returns (address payable);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/SIDRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\ninterface SIDRegistryInterface {\n function resolver(bytes32 node) external view returns (address);\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/oracles/BinanceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/SIDRegistryInterface.sol\";\nimport \"../interfaces/FeedRegistryInterface.sol\";\nimport \"../interfaces/PublicResolverInterface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport \"../interfaces/OracleInterface.sol\";\n\n/**\n * @title BinanceOracle\n * @author Venus\n * @notice This oracle fetches price of assets from Binance.\n */\ncontract BinanceOracle is AccessControlledV8, OracleInterface {\n address public sidRegistryAddress;\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Max stale period configuration for assets\n mapping(string => uint256) public maxStalePeriod;\n\n /// @notice Override symbols to be compatible with Binance feed registry\n mapping(string => string) public symbols;\n\n event MaxStalePeriodAdded(string indexed asset, uint256 maxStalePeriod);\n\n event SymbolOverridden(string indexed symbol, string overriddenSymbol);\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 /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Used to set the max stale period of an asset\n * @param symbol The symbol of the asset\n * @param _maxStalePeriod The max stake period\n */\n function setMaxStalePeriod(string memory symbol, uint256 _maxStalePeriod) external {\n _checkAccessAllowed(\"setMaxStalePeriod(string,uint256)\");\n if (_maxStalePeriod == 0) revert(\"stale period can't be zero\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n maxStalePeriod[symbol] = _maxStalePeriod;\n emit MaxStalePeriodAdded(symbol, _maxStalePeriod);\n }\n\n /**\n * @notice Used to override a symbol when fetching price\n * @param symbol The symbol to override\n * @param overrideSymbol The symbol after override\n */\n function setSymbolOverride(string calldata symbol, string calldata overrideSymbol) external {\n _checkAccessAllowed(\"setSymbolOverride(string,string)\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n symbols[symbol] = overrideSymbol;\n emit SymbolOverridden(symbol, overrideSymbol);\n }\n\n /**\n * @notice Sets the contracts required to fetch prices\n * @param _sidRegistryAddress Address of SID registry\n * @param _accessControlManager Address of the access control manager contract\n */\n function initialize(\n address _sidRegistryAddress,\n address _accessControlManager\n ) external initializer notNullAddress(_sidRegistryAddress) {\n sidRegistryAddress = _sidRegistryAddress;\n __AccessControlled_init(_accessControlManager);\n }\n\n /**\n * @notice Uses Space ID to fetch the feed registry address\n * @return feedRegistryAddress Address of binance oracle feed registry.\n */\n function getFeedRegistryAddress() public view returns (address) {\n bytes32 nodeHash = 0x94fe3821e0768eb35012484db4df61890f9a6ca5bfa984ef8ff717e73139faff;\n\n SIDRegistryInterface sidRegistry = SIDRegistryInterface(sidRegistryAddress);\n address publicResolverAddress = sidRegistry.resolver(nodeHash);\n PublicResolverInterface publicResolver = PublicResolverInterface(publicResolverAddress);\n\n return publicResolver.addr(nodeHash);\n }\n\n /**\n * @notice Gets the price of a asset from the binance oracle\n * @param asset Address of the asset\n * @return Price in USD\n */\n function getPrice(address asset) public view returns (uint256) {\n string memory symbol;\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n symbol = \"BNB\";\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n symbol = token.symbol();\n decimals = token.decimals();\n }\n\n string memory overrideSymbol = symbols[symbol];\n\n if (bytes(overrideSymbol).length != 0) {\n symbol = overrideSymbol;\n }\n\n return _getPrice(symbol, decimals);\n }\n\n function _getPrice(string memory symbol, uint256 decimals) internal view returns (uint256) {\n FeedRegistryInterface feedRegistry = FeedRegistryInterface(getFeedRegistryAddress());\n\n (, int256 answer, , uint256 updatedAt, ) = feedRegistry.latestRoundDataByName(symbol, \"USD\");\n if (answer <= 0) revert(\"invalid binance oracle price\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n if (deltaTime > maxStalePeriod[symbol]) revert(\"binance oracle price expired\");\n\n uint256 decimalDelta = feedRegistry.decimalsByName(symbol, \"USD\");\n return (uint256(answer) * (10 ** (18 - decimalDelta))) * (10 ** (18 - decimals));\n }\n}\n" + }, + "@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ChainlinkOracle\n * @author Venus\n * @notice This oracle fetches prices of assets from the Chainlink oracle.\n */\ncontract ChainlinkOracle is AccessControlledV8, OracleInterface {\n struct TokenConfig {\n /// @notice Underlying token address, which can't be a null address\n /// @notice Used to check if a token is supported\n /// @notice 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB for BNB\n address asset;\n /// @notice Chainlink feed address\n address feed;\n /// @notice Price expiration period of this asset\n uint256 maxStalePeriod;\n }\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Manually set an override price, useful under extenuating conditions such as price feed failure\n mapping(address => uint256) public prices;\n\n /// @notice Token config by assets\n mapping(address => TokenConfig) public tokenConfigs;\n\n /// @notice Emit when a price is manually set\n event PricePosted(address indexed asset, uint256 previousPriceMantissa, uint256 newPriceMantissa);\n\n /// @notice Emit when a token config is added\n event TokenConfigAdded(address indexed asset, address feed, uint256 maxStalePeriod);\n\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Manually set the price of a given asset\n * @param asset Asset address\n * @param price Asset price in 18 decimals\n * @custom:access Only Governance\n * @custom:event Emits PricePosted event on succesfully setup of asset price\n */\n function setDirectPrice(address asset, uint256 price) external notNullAddress(asset) {\n _checkAccessAllowed(\"setDirectPrice(address,uint256)\");\n\n uint256 previousPriceMantissa = prices[asset];\n prices[asset] = price;\n emit PricePosted(asset, previousPriceMantissa, price);\n }\n\n /**\n * @notice Add multiple token configs at the same time\n * @param tokenConfigs_ config array\n * @custom:access Only Governance\n * @custom:error Zero length error thrown, if length of the array in parameter 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 Initializes the owner of the contract\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n }\n\n /**\n * @notice Add single token config. asset & feed cannot be null addresses and maxStalePeriod must be positive\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error NotNullAddress error is thrown if token feed address is null\n * @custom:error Range error is thrown if maxStale period of token is not greater than zero\n * @custom:event Emits TokenConfigAdded event on succesfully setting of the token config\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.feed) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n if (tokenConfig.maxStalePeriod == 0) revert(\"stale period can't be zero\");\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(tokenConfig.asset, tokenConfig.feed, tokenConfig.maxStalePeriod);\n }\n\n /**\n * @notice Gets the price of a asset from the chainlink oracle\n * @param asset Address of the asset\n * @return Price in USD from Chainlink or a manually set price for the asset\n */\n function getPrice(address asset) public view returns (uint256) {\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n decimals = token.decimals();\n }\n\n return _getPriceInternal(asset, decimals);\n }\n\n /**\n * @notice Gets the Chainlink price for a given asset\n * @param asset address of the asset\n * @param decimals decimals of the asset\n * @return price Asset price in USD or a manually set price of the asset\n */\n function _getPriceInternal(address asset, uint256 decimals) internal view returns (uint256 price) {\n uint256 tokenPrice = prices[asset];\n if (tokenPrice != 0) {\n price = tokenPrice;\n } else {\n price = _getChainlinkPrice(asset);\n }\n\n uint256 decimalDelta = 18 - decimals;\n return price * (10 ** decimalDelta);\n }\n\n /**\n * @notice Get the Chainlink price for an asset, revert if token config doesn't exist\n * @dev The precision of the price feed is used to ensure the returned price has 18 decimals of precision\n * @param asset Address of the asset\n * @return price Price in USD, with 18 decimals of precision\n * @custom:error NotNullAddress error is thrown if the asset address is null\n * @custom:error Price error is thrown if the Chainlink price of asset is not greater than zero\n * @custom:error Timing error is thrown if current timestamp is less than the last updatedAt timestamp\n * @custom:error Timing error is thrown if time difference between current time and last updated time\n * is greater than maxStalePeriod\n */\n function _getChainlinkPrice(\n address asset\n ) private view notNullAddress(tokenConfigs[asset].asset) returns (uint256) {\n TokenConfig memory tokenConfig = tokenConfigs[asset];\n AggregatorV3Interface feed = AggregatorV3Interface(tokenConfig.feed);\n\n // note: maxStalePeriod cannot be 0\n uint256 maxStalePeriod = tokenConfig.maxStalePeriod;\n\n // Chainlink USD-denominated feeds store answers at 8 decimals, mostly\n uint256 decimalDelta = 18 - feed.decimals();\n\n (, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData();\n if (answer <= 0) revert(\"chainlink price must be positive\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n\n if (deltaTime > maxStalePeriod) revert(\"chainlink price expired\");\n\n return uint256(answer) * (10 ** decimalDelta);\n }\n}\n" + }, + "@venusprotocol/protocol-reserve/contracts/Interfaces/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface ComptrollerInterface {\n function isComptroller() external view returns (bool);\n}\n" + }, + "@venusprotocol/protocol-reserve/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" + }, + "@venusprotocol/protocol-reserve/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" + }, + "@venusprotocol/protocol-reserve/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" + }, + "@venusprotocol/protocol-reserve/contracts/Interfaces/PoolRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface PoolRegistryInterface {\n /*** get VToken in the Pool for an Asset ***/\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n}\n" + }, + "@venusprotocol/protocol-reserve/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\";\n\nimport { IProtocolShareReserve } from \"../Interfaces/IProtocolShareReserve.sol\";\nimport { ComptrollerInterface } from \"../Interfaces/ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Interfaces/PoolRegistryInterface.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 uint8 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 uint8 public constant MAX_PERCENT = 100;\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 the updation 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 uint8 oldPercentage,\n uint8 newPercentage,\n Schema schema\n );\n\n /// @notice Event emitted when distribution configuration is added\n event DistributionConfigAdded(address indexed destination, uint8 percentage, Schema schema);\n\n /// @notice Event emitted when distribution configuration is removed\n event DistributionConfigRemoved(address indexed destination, uint8 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 if (_corePoolComptroller == address(0)) revert InvalidAddress();\n if (_wbnb == address(0)) revert InvalidAddress();\n if (_vbnb == address(0)) revert InvalidAddress();\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 */\n function setPoolRegistry(address _poolRegistry) external onlyOwner {\n if (_poolRegistry == address(0)) revert InvalidAddress();\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 if (_config.destination == address(0)) revert InvalidAddress();\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 (!ComptrollerInterface(comptroller).isComptroller()) revert InvalidAddress();\n if (asset == address(0)) revert InvalidAddress();\n if (\n comptroller != CORE_POOL_COMPTROLLER &&\n PoolRegistryInterface(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 uint8[] memory totalPercentages = new uint8[](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" + }, + "@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" + }, + "contracts/BaseJumpRateModelV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { BLOCKS_PER_YEAR, EXP_SCALE, MANTISSA_ONE } from \"./lib/constants.sol\";\n\n/**\n * @title Logic for Compound's JumpRateModel Contract V2.\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\n */\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\n /**\n * @notice The address of the AccessControlManager contract\n */\n IAccessControlManagerV8 public accessControlManager;\n\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public baseRatePerBlock;\n\n /**\n * @notice The multiplier per block after hitting a specified utilization point\n */\n uint256 public jumpMultiplierPerBlock;\n\n /**\n * @notice The utilization point at which the jump multiplier is applied\n */\n uint256 public kink;\n\n event NewInterestParams(\n uint256 baseRatePerBlock,\n uint256 multiplierPerBlock,\n uint256 jumpMultiplierPerBlock,\n uint256 kink\n );\n\n /**\n * @notice Thrown when the action is prohibited by AccessControlManager\n */\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n /**\n * @notice Construct an interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n * @param accessControlManager_ The address of the AccessControlManager contract\n */\n constructor(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_,\n IAccessControlManagerV8 accessControlManager_\n ) {\n require(address(accessControlManager_) != address(0), \"invalid ACM address\");\n\n accessControlManager = accessControlManager_;\n\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\n }\n\n /**\n * @notice Update the parameters of the interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n * @custom:error Unauthorized if the sender is not allowed to call this function\n * @custom:access Controlled by AccessControlManager\n */\n function updateJumpRateModel(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_\n ) external virtual {\n string memory signature = \"updateJumpRateModel(uint256,uint256,uint256,uint256)\";\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) public view virtual override returns (uint256) {\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\n uint256 incomeToDistribute = borrows * rateToPool;\n uint256 supply = cash + borrows + badDebt - reserves;\n return incomeToDistribute / supply;\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @param badDebt The amount of badDebt in the market\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\n */\n function utilizationRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows and badDebt\n if ((borrows + badDebt) == 0) {\n return 0;\n }\n\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\n\n if (rate > EXP_SCALE) {\n rate = EXP_SCALE;\n }\n\n return rate;\n }\n\n /**\n * @notice Internal function to update the parameters of the interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n */\n function _updateJumpRateModel(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_\n ) internal {\n baseRatePerBlock = baseRatePerYear / BLOCKS_PER_YEAR;\n multiplierPerBlock = multiplierPerYear / BLOCKS_PER_YEAR;\n jumpMultiplierPerBlock = jumpMultiplierPerYear / BLOCKS_PER_YEAR;\n kink = kink_;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function _getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) internal view returns (uint256) {\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\n uint256 kink_ = kink;\n\n if (util <= kink_) {\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n }\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n uint256 excessUtil;\n unchecked {\n excessUtil = util - kink_;\n }\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\n }\n}\n" + }, + "contracts/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\n\n /// @notice Emitted when a collateral factor is changed by admin\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\n );\n\n /// @notice Emitted when liquidation incentive is changed by admin\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\n\n /// @notice Emitted when borrow cap for a vToken is changed\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\n\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\n\n /// @notice Emitted when supply cap for a vToken is changed\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\n\n /// @notice Emitted when a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow.\n * @param vTokenAddress The address of the asset to be removed\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\n\n Market storage marketToExit = markets[address(vToken)];\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return NO_ERROR;\n }\n\n /* Set vToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete vToken from the account’s list of assets */\n // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\n\n /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param vToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param vToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param vToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param vToken The market to verify the repay against\n * @param borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if it is a forced liquidation */\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\n }\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param vToken The market to verify the transfer against\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\n _checkActionPauseState(vToken, Action.TRANSFER);\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = accountAssets[user];\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = accountAssets[borrower];\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\n // Set liquidation incentive to new incentive\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n // Emit event with old incentive, new incentive\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"setMarketBorrowCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \"invalid input\");\n\n _ensureMaxLoops(numMarkets);\n\n for (uint256 i; i < numMarkets; ++i) {\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\n }\n }\n\n /**\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Enables forced liquidations for a market. If forced liquidation is enabled,\n * borrows in the market may be liquidated regardless of the account liquidity\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n _checkAccessAllowed(\"setForcedLiquidation(address,bool)\");\n ensureNonzeroAddress(vTokenBorrowed);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(vTokenBorrowed);\n }\n\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall Hypothetical account shortfall below collateral requirements\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market.\n * @return markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\n }\n\n /**\n * @notice Check if a market is marked as listed (active)\n * @param vToken vToken Address for the market to check\n * @return listed True if listed otherwise false\n */\n function isMarketListed(VToken vToken) external view returns (bool) {\n return markets[address(vToken)].isListed;\n }\n\n /*** Assets You Are In ***/\n\n /**\n * @notice Returns the assets an account has entered\n * @param account The address of the account to pull assets for\n * @return A list with the assets the account has entered\n */\n function getAssetsIn(address account) external view returns (VToken[] memory) {\n VToken[] memory assetsIn = accountAssets[account];\n\n return assetsIn;\n }\n\n /**\n * @notice Returns whether the given account is entered in a given market\n * @param account The address of the account to check\n * @param vToken The vToken to check\n * @return True if the account is in the market specified, otherwise false.\n */\n function checkMembership(address account, VToken vToken) external view returns (bool) {\n return markets[address(vToken)].accountMembership[account];\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = accountAssets[account];\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param vToken The market to enter\n * @param borrower The address of the account to modify\n */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\n\n // survived the gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n accountAssets[borrower].push(vToken);\n\n emit MarketEntered(vToken, borrower);\n }\n\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\n }\n\n /**\n * @dev Pause/unpause an action on a market\n * @param market Market to pause/unpause the action on\n * @param action Action id to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n */\n function _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = accountAssets[account];\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\n\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // Multiplier representing the most one can borrow against their collateral in this market.\n // For instance, 0.9 to allow borrowing 90% of collateral value.\n // Must be between 0 and 1, and stored as a mantissa.\n uint256 collateralFactorMantissa;\n // Multiplier representing the collateralization after which the borrow is eligible\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\n // value. Must be between 0 and collateral factor, stored as a mantissa.\n uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\n enum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n }\n\n /**\n * @notice Oracle which gives the price of any given asset\n */\n ResilientOracleInterface public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\n uint256 public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives\n */\n uint256 public liquidationIncentiveMantissa;\n\n /**\n * @notice Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\n\n /**\n * @notice Official mapping of vTokens -> Market metadata\n * @dev Used e.g. to determine if a market is supported\n */\n mapping(address => Market) public markets;\n\n /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n /// @notice Flag indicating whether forced liquidation enabled for a market\n mapping(address => bool) public isForcedLiquidationEnabled;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\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" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Compound\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract ExponentialNoError {\n struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return truncate(product);\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return add_(truncate(product), addend);\n }\n\n /**\n * @dev Checks if first Exp is less than second Exp.\n */\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa < right.mantissa;\n }\n\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, errorMessage);\n return uint32(n);\n }\n\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\n }\n\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), b.mantissa);\n }\n\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/IPancakeswapV2Router.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPancakeswapV2Router {\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n}\n" + }, + "contracts/JumpRateModelV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { BaseJumpRateModelV2 } from \"./BaseJumpRateModelV2.sol\";\n\n/**\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\n * @author Arr00\n * @notice Supports only for V2 vTokens\n */\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\n constructor(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_,\n IAccessControlManagerV8 accessControlManager_\n )\n BaseJumpRateModelV2(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_, accessControlManager_)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n /**\n * @notice Calculates the current borrow rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view override returns (uint256) {\n return _getBorrowRate(cash, borrows, reserves, badDebt);\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlock;\n uint256 borrowRatePerBlock;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = comptroller.getAllMarkets();\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\n\n return\n VTokenBalances({\n vToken: address(vToken),\n balanceOf: balanceOf,\n borrowBalanceCurrent: borrowBalanceCurrent,\n balanceOfUnderlying: balanceOfUnderlying,\n tokenBalance: tokenBalance,\n tokenAllowance: tokenAllowance\n });\n }\n\n /**\n * @notice Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlock: vToken.supplyRatePerBlock(),\n borrowRatePerBlock: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(address(vToken.comptroller()));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n return\n VTokenUnderlyingPrice({\n vToken: address(vToken),\n underlyingPrice: priceOracle.getUnderlyingPrice(address(vToken))\n });\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n (borrowState.index, borrowState.block, borrowState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenBorrowState(address(markets[i]));\n RewardTokenState memory supplyState;\n (supplyState.index, supplyState.block, supplyState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenSupplyState(address(markets[i]));\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, borrowAmount) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: borrowState.index }), ratio);\n borrowState.index = safe224(index.mantissa, \"new index overflows\");\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(supplyState.block));\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, supplyTokens) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: supplyState.index }), ratio);\n supplyState.index = safe224(index.mantissa, \"new index overflows\");\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/ApproveOrRevert.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nlibrary ApproveOrRevert {\n /// @notice Thrown if a contract is unable to approve a transfer\n error ApproveFailed();\n\n /// @notice Approves a transfer, ensuring that it is successful. This function supports non-compliant\n /// tokens like the ones that don't return a boolean value on success. Thus, such approve call supports\n /// three different kinds of tokens:\n /// * Compliant tokens that revert on failure\n /// * Compliant tokens that return false on failure\n /// * Non-compliant tokens that don't return a value\n /// @param token The contract address of the token which will be transferred\n /// @param spender The spender contract address\n /// @param amount The value of the transfer\n function approveOrRevert(IERC20Upgradeable token, address spender, uint256 amount) internal {\n bytes memory callData = abi.encodeCall(token.approve, (spender, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory result) = address(token).call(callData);\n\n if (!success || (result.length != 0 && !abi.decode(result, (bool)))) {\n revert ApproveFailed();\n }\n }\n}\n" + }, + "contracts/lib/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/// @dev The approximate number of blocks per year that is assumed by the interest rate model\nuint256 constant BLOCKS_PER_YEAR = 10_512_000;\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" + }, + "contracts/lib/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/lib/TokenDebtTracker.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n/**\n * @title TokenDebtTracker\n * @author Venus\n * @notice TokenDebtTracker is an abstract contract that handles transfers _out_ of the inheriting contract.\n * If there is an error transferring out (due to any reason, e.g. the token contract restricted the user from\n * receiving incoming transfers), the amount is recorded as a debt that can be claimed later.\n * @dev Note that the inheriting contract keeps some amount of users' tokens on its balance, so be careful when\n * using balanceOf(address(this))!\n */\nabstract contract TokenDebtTracker is Initializable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => (address user => uint256 amount)).\n * Tracks failed transfers: when a token transfer fails, we record the\n * amount of the transfer, so that the user can redeem this debt later.\n */\n mapping(IERC20Upgradeable => mapping(address => uint256)) public tokenDebt;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => uint256 amount) shows how many\n * tokens the contract owes to all users. This is useful for accounting to\n * understand how much of balanceOf(address(this)) is already owed to users.\n */\n mapping(IERC20Upgradeable => uint256) public totalTokenDebt;\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[48] private __gap;\n\n /**\n * @notice Emitted when the contract's debt to the user is increased due to a failed transfer\n * @param token Token address\n * @param user User address\n * @param amount The amount of debt added\n */\n event TokenDebtAdded(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Emitted when a user claims tokens that the contract owes them\n * @param token Token address\n * @param user User address\n * @param amount The amount transferred\n */\n event TokenDebtClaimed(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Thrown if the user tries to claim more tokens than they are owed\n * @param token The token the user is trying to claim\n * @param owedAmount The amount of tokens the contract owes to the user\n * @param amount The amount of tokens the user is trying to claim\n */\n error InsufficientDebt(address token, address user, uint256 owedAmount, uint256 amount);\n\n /**\n * @notice Thrown if trying to transfer more tokens than the contract currently has\n * @param token The token the contract is trying to transfer\n * @param recipient The recipient of the transfer\n * @param amount The amount of tokens the contract is trying to transfer\n * @param availableBalance The amount of tokens the contract currently has\n */\n error InsufficientBalance(address token, address recipient, uint256 amount, uint256 availableBalance);\n\n /**\n * @notice Transfers the tokens we owe to msg.sender, if any\n * @param token The token to claim\n * @param amount_ The amount of tokens to claim (or max uint256 to claim all)\n * @custom:error InsufficientDebt The contract doesn't have enough debt to the user\n */\n function claimTokenDebt(IERC20Upgradeable token, uint256 amount_) external {\n uint256 owedAmount = tokenDebt[token][msg.sender];\n uint256 amount = (amount_ == type(uint256).max ? owedAmount : amount_);\n if (amount > owedAmount) {\n revert InsufficientDebt(address(token), msg.sender, owedAmount, amount);\n }\n unchecked {\n // Safe because we revert if amount > owedAmount above\n tokenDebt[token][msg.sender] = owedAmount - amount;\n }\n totalTokenDebt[token] -= amount;\n emit TokenDebtClaimed(address(token), msg.sender, amount);\n token.safeTransfer(msg.sender, amount);\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function __TokenDebtTracker_init() internal onlyInitializing {\n __TokenDebtTracker_init_unchained();\n }\n\n // solhint-disable-next-line func-name-mixedcase, no-empty-blocks\n function __TokenDebtTracker_init_unchained() internal onlyInitializing {}\n\n /**\n * @dev Transfers tokens to the recipient if the contract has enough balance, or\n * records the debt if the transfer fails due to reasons unrelated to the contract's\n * balance (e.g. if the token forbids transfers to the recipient).\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @custom:error InsufficientBalance The contract doesn't have enough balance to transfer\n */\n function _transferOutOrTrackDebt(IERC20Upgradeable token, address to, uint256 amount) internal {\n uint256 balance = token.balanceOf(address(this));\n if (balance < amount) {\n revert InsufficientBalance(address(token), address(this), amount, balance);\n }\n _transferOutOrTrackDebtSkippingBalanceCheck(token, to, amount);\n }\n\n /**\n * @dev Transfers tokens to the recipient, or records the debt if the transfer fails\n * due to any reason, including insufficient balance.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n */\n function _transferOutOrTrackDebtSkippingBalanceCheck(IERC20Upgradeable token, address to, uint256 amount) internal {\n // We can't use safeTransfer here because we can't try-catch internal calls\n bool success = _tryTransferOut(token, to, amount);\n if (!success) {\n tokenDebt[token][to] += amount;\n totalTokenDebt[token] += amount;\n emit TokenDebtAdded(address(token), to, amount);\n }\n }\n\n /**\n * @dev Either transfers tokens to the recepient or returns false. Supports tokens\n * thet revert or return false to indicate failure, and the non-compliant ones\n * that do not return any value.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @return true if the transfer succeeded, false otherwise\n */\n function _tryTransferOut(IERC20Upgradeable token, address to, uint256 amount) private returns (bool) {\n bytes memory callData = abi.encodeCall(token.transfer, (to, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = address(token).call(callData);\n return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n }\n}\n" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\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\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\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 /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.approve(vTokenAddress, 0);\n underlying.approve(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title PoolRegistryInterface\n * @author Venus\n * @notice Interface implemented by `PoolRegistry`.\n */\ninterface PoolRegistryInterface {\n /**\n * @notice Struct for a Venus interest rate pool.\n */\n struct VenusPool {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n }\n\n /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each block for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller private comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n function initializeMarket(address vToken) external onlyComptroller {\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlock(address[],uint32[],uint32[])\");\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumber();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\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 */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumber = getBlockNumber();\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumber;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n function getBlockNumber() public view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumber();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\n * @param vToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n uint256 supplyIndex = supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n uint256 borrowIndex = borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\n\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n supplyState.index = safe224(\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n supplyState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n supplyState.block = blockNumber;\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n borrowState.index = safe224(\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n borrowState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n borrowState.block = blockNumber;\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n}\n" + }, + "contracts/RiskFund/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 swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external returns (uint256);\n\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updateAssetsState(address comptroller, address asset) external;\n\n function convertibleBaseAsset() external view returns (address);\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n" + }, + "contracts/RiskFund/ReserveHelpers.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { VToken } from \"../VToken.sol\";\n\ncontract ReserveHelpers is Ownable2StepUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 private constant NOT_ENTERED = 1;\n\n uint256 private constant ENTERED = 2;\n\n // Address of the core pool's comptroller\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n // Address of the VBNB\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable VBNB;\n\n // Address of the native wrapped token\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_WRAPPED;\n\n // Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools).\n mapping(address => uint256) public assetsReserves;\n\n // Store the asset's reserve per pool in the ProtocolShareReserve.\n // Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal _poolsAssetsReserves;\n\n // Address of pool registry contract\n address public poolRegistry;\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n uint256 internal status;\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 */\n uint256[46] private __gap;\n\n /// @notice Event emitted after the update of the assets reserves.\n /// @param comptroller Pool's Comptroller address\n /// @param asset Token address\n /// @param amount An amount by which the reserves have increased\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice event emitted on sweep token success\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(status != ENTERED, \"re-entered\");\n status = ENTERED;\n _;\n status = NOT_ENTERED;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address corePoolComptroller_, address vbnb_, address nativeWrapped_) {\n ensureNonzeroAddress(corePoolComptroller_);\n ensureNonzeroAddress(vbnb_);\n ensureNonzeroAddress(nativeWrapped_);\n\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\n VBNB = vbnb_;\n NATIVE_WRAPPED = nativeWrapped_;\n }\n\n /**\n * @notice A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input\n * @param _token The address of the BEP-20 token to sweep\n * @param _to Recipient of the output tokens.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n * @custom:access Only Owner\n */\n function sweepToken(address _token, address _to) external onlyOwner nonReentrant {\n ensureNonzeroAddress(_to);\n uint256 balanceDfference_;\n uint256 balance_ = IERC20Upgradeable(_token).balanceOf(address(this));\n\n require(balance_ > assetsReserves[_token], \"ReserveHelpers: Zero surplus tokens\");\n unchecked {\n balanceDfference_ = balance_ - assetsReserves[_token];\n }\n\n emit SweepToken(_token, _to, balanceDfference_);\n IERC20Upgradeable(_token).safeTransfer(_to, balanceDfference_);\n }\n\n /**\n * @notice 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 Asset's reserve in risk fund.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256) {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][asset];\n }\n\n /**\n * @notice 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 * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function updateAssetsState(address comptroller, address asset) public virtual {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n address poolRegistry_ = poolRegistry;\n require(poolRegistry_ != address(0), \"ReserveHelpers: Pool Registry address is not set\");\n require(ensureAssetListed(comptroller, asset), \"ReserveHelpers: The pool doesn't support the asset\");\n\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n assetsReserves[asset] += balanceDifference;\n _poolsAssetsReserves[comptroller][asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference);\n }\n }\n\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\n VToken[] memory coreMarkets = ComptrollerInterface(CORE_POOL_COMPTROLLER).getAllMarkets();\n\n for (uint256 i; i < coreMarkets.length; ++i) {\n isAssetListed = (VBNB == address(coreMarkets[i]))\n ? (tokenAddress == NATIVE_WRAPPED)\n : (coreMarkets[i].underlying() == tokenAddress);\n\n if (isAssetListed) {\n break;\n }\n }\n }\n\n /// @notice 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 function ensureAssetListed(address comptroller, address asset) internal view returns (bool) {\n if (comptroller == CORE_POOL_COMPTROLLER) {\n return isAssetListedInCore(asset);\n }\n\n return PoolRegistryInterface(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\n }\n}\n" + }, + "contracts/RiskFund/RiskFund.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 { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { IRiskFund } from \"./IRiskFund.sol\";\nimport { ReserveHelpers } from \"./ReserveHelpers.sol\";\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { IPancakeswapV2Router } from \"../IPancakeswapV2Router.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { ApproveOrRevert } from \"../lib/ApproveOrRevert.sol\";\n\n/**\n * @title RiskFund\n * @author Venus\n * @notice Contract with basic features to track/hold different assets for different Comptrollers.\n * @dev This contract does not support BNB.\n */\ncontract RiskFund is AccessControlledV8, ExponentialNoError, ReserveHelpers, MaxLoopsLimitHelper, IRiskFund {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using ApproveOrRevert for IERC20Upgradeable;\n\n address public convertibleBaseAsset;\n address public shortfall;\n address public pancakeSwapRouter;\n uint256 public minAmountToConvert;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when shortfall contract address is updated\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\n\n /// @notice Emitted when convertible base asset is updated\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\n\n /// @notice Emitted when PancakeSwap router contract address is updated\n event PancakeSwapRouterUpdated(address indexed oldPancakeSwapRouter, address indexed newPancakeSwapRouter);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Emitted when pools assets are swapped\n event SwappedPoolsAssets(address[] markets, uint256[] amountsOutMin, uint256 totalAmount);\n\n /// @notice Emitted when reserves are transferred for auction\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\n\n /// @dev Note that the contract is upgradeable. Use initialize() or reinitializers\n /// to set the state variables.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address corePoolComptroller_,\n address vbnb_,\n address nativeWrapped_\n ) ReserveHelpers(corePoolComptroller_, vbnb_, nativeWrapped_) {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner.\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @param minAmountToConvert_ Minimum amount assets must be worth to convert into base asset\n * @param convertibleBaseAsset_ Address of the base asset\n * @param accessControlManager_ Address of the access control contract\n * @param loopsLimit_ Limit for the loops in the contract to avoid DOS\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n */\n function initialize(\n address pancakeSwapRouter_,\n uint256 minAmountToConvert_,\n address convertibleBaseAsset_,\n address accessControlManager_,\n uint256 loopsLimit_\n ) external initializer {\n ensureNonzeroAddress(pancakeSwapRouter_);\n ensureNonzeroAddress(convertibleBaseAsset_);\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n require(loopsLimit_ > 0, \"Risk Fund: Loops limit can not be zero\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n pancakeSwapRouter = pancakeSwapRouter_;\n minAmountToConvert = minAmountToConvert_;\n convertibleBaseAsset = convertibleBaseAsset_;\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice 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 address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Shortfall contract address setter\n * @param shortfallContractAddress_ Address of the auction contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n */\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\n ensureNonzeroAddress(shortfallContractAddress_);\n\n address oldShortfallContractAddress = shortfall;\n shortfall = shortfallContractAddress_;\n emit ShortfallContractUpdated(oldShortfallContractAddress, shortfallContractAddress_);\n }\n\n /**\n * @notice PancakeSwap router address setter\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n */\n function setPancakeSwapRouter(address pancakeSwapRouter_) external onlyOwner {\n ensureNonzeroAddress(pancakeSwapRouter_);\n address oldPancakeSwapRouter = pancakeSwapRouter;\n pancakeSwapRouter = pancakeSwapRouter_;\n emit PancakeSwapRouterUpdated(oldPancakeSwapRouter, pancakeSwapRouter_);\n }\n\n /**\n * @notice Min amount to convert setter\n * @param minAmountToConvert_ Min amount to convert.\n */\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n uint256 oldMinAmountToConvert = minAmountToConvert;\n minAmountToConvert = minAmountToConvert_;\n emit MinAmountToConvertUpdated(oldMinAmountToConvert, minAmountToConvert_);\n }\n\n /**\n * @notice Sets a new convertible base asset\n * @param _convertibleBaseAsset Address for new convertible base asset.\n */\n function setConvertibleBaseAsset(address _convertibleBaseAsset) external {\n _checkAccessAllowed(\"setConvertibleBaseAsset(address)\");\n require(_convertibleBaseAsset != address(0), \"Risk Fund: new convertible base asset address invalid\");\n\n address oldConvertibleBaseAsset = convertibleBaseAsset;\n convertibleBaseAsset = _convertibleBaseAsset;\n\n emit ConvertibleBaseAssetUpdated(oldConvertibleBaseAsset, _convertibleBaseAsset);\n }\n\n /**\n * @notice Swap array of pool assets into base asset's tokens of at least a minimum amount\n * @param markets Array of vTokens whose assets to swap for base asset\n * @param amountsOutMin Minimum amount to receive for swap\n * @param paths A path consisting of PCS token pairs for each swap\n * @param deadline Deadline for the swap\n * @return Number of swapped tokens\n * @custom:error ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\n */\n function swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external override nonReentrant returns (uint256) {\n _checkAccessAllowed(\"swapPoolsAssets(address[],uint256[],address[][],uint256)\");\n require(deadline >= block.timestamp, \"Risk fund: deadline passed\");\n address poolRegistry_ = poolRegistry;\n ensureNonzeroAddress(poolRegistry_);\n require(markets.length == amountsOutMin.length, \"Risk fund: markets and amountsOutMin are unequal lengths\");\n require(markets.length == paths.length, \"Risk fund: markets and paths are unequal lengths\");\n\n uint256 totalAmount;\n uint256 marketsCount = markets.length;\n\n _ensureMaxLoops(marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n address comptroller = address(VToken(markets[i]).comptroller());\n\n PoolRegistry.VenusPool memory pool = PoolRegistry(poolRegistry_).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n require(Comptroller(comptroller).isMarketListed(VToken(markets[i])), \"market is not listed\");\n\n uint256 swappedTokens = _swapAsset(VToken(markets[i]), comptroller, amountsOutMin[i], paths[i]);\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] += swappedTokens;\n assetsReserves[convertibleBaseAsset] += swappedTokens;\n totalAmount = totalAmount + swappedTokens;\n }\n\n emit SwappedPoolsAssets(markets, amountsOutMin, totalAmount);\n\n return totalAmount;\n }\n\n /**\n * @notice Transfer tokens for auction.\n * @param comptroller Comptroller of the pool.\n * @param amount Amount to be transferred to auction contract.\n * @return Number reserved tokens.\n */\n function transferReserveForAuction(\n address comptroller,\n uint256 amount\n ) external override nonReentrant returns (uint256) {\n address shortfall_ = shortfall;\n require(msg.sender == shortfall_, \"Risk fund: Only callable by Shortfall contract\");\n require(\n amount <= _poolsAssetsReserves[comptroller][convertibleBaseAsset],\n \"Risk Fund: Insufficient pool reserve.\"\n );\n unchecked {\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] =\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] -\n amount;\n }\n unchecked {\n assetsReserves[convertibleBaseAsset] = assetsReserves[convertibleBaseAsset] - amount;\n }\n\n emit TransferredReserveForAuction(comptroller, amount);\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall_, amount);\n\n return amount;\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 */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\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 require(ComptrollerInterface(comptroller).isComptroller(), \"Risk Fund: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][convertibleBaseAsset];\n }\n\n /**\n * @notice Update the reserve of the asset for the specific pool after transferring to risk fund.\n * @param comptroller Comptroller address(pool).\n * @param asset Asset address.\n */\n function updateAssetsState(address comptroller, address asset) public override(IRiskFund, ReserveHelpers) {\n super.updateAssetsState(comptroller, asset);\n }\n\n /**\n * @dev Swap single asset to base asset.\n * @param vToken VToken\n * @param comptroller Comptroller address\n * @param amountOutMin Minimum amount to receive for swap\n * @param path A path for the swap consisting of PCS token pairs\n * @return Number of swapped tokens.\n */\n function _swapAsset(\n VToken vToken,\n address comptroller,\n uint256 amountOutMin,\n address[] calldata path\n ) internal returns (uint256) {\n require(amountOutMin != 0, \"RiskFund: amountOutMin must be greater than 0 to swap vToken\");\n uint256 totalAmount;\n\n address underlyingAsset = vToken.underlying();\n address convertibleBaseAsset_ = convertibleBaseAsset;\n uint256 balanceOfUnderlyingAsset = _poolsAssetsReserves[comptroller][underlyingAsset];\n\n if (balanceOfUnderlyingAsset == 0) {\n return 0;\n }\n\n ResilientOracleInterface oracle = ComptrollerViewInterface(comptroller).oracle();\n oracle.updateAssetPrice(convertibleBaseAsset_);\n Exp memory baseAssetPrice = Exp({ mantissa: oracle.getPrice(convertibleBaseAsset_) });\n uint256 amountOutMinInUsd = mul_ScalarTruncate(baseAssetPrice, amountOutMin);\n\n require(amountOutMinInUsd >= minAmountToConvert, \"RiskFund: minAmountToConvert violated\");\n\n assetsReserves[underlyingAsset] -= balanceOfUnderlyingAsset;\n _poolsAssetsReserves[comptroller][underlyingAsset] -= balanceOfUnderlyingAsset;\n\n if (underlyingAsset != convertibleBaseAsset_) {\n require(path[0] == underlyingAsset, \"RiskFund: swap path must start with the underlying asset\");\n require(\n path[path.length - 1] == convertibleBaseAsset_,\n \"RiskFund: finally path must be convertible base asset\"\n );\n address pancakeSwapRouter_ = pancakeSwapRouter;\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, 0);\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, balanceOfUnderlyingAsset);\n uint256[] memory amounts = IPancakeswapV2Router(pancakeSwapRouter_).swapExactTokensForTokens(\n balanceOfUnderlyingAsset,\n amountOutMin,\n path,\n address(this),\n block.timestamp\n );\n totalAmount = amounts[path.length - 1];\n } else {\n totalAmount = balanceOfUnderlyingAsset;\n }\n\n return totalAmount;\n }\n}\n" + }, + "contracts/Shortfall/Shortfall.sol": { + "content": "/// @notice SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { IRiskFund } from \"../RiskFund/IRiskFund.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { TokenDebtTracker } from \"../lib/TokenDebtTracker.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { EXP_SCALE } from \"../lib/constants.sol\";\n\n/**\n * @title Shortfall\n * @author Venus\n * @notice Shortfall is an auction contract designed to auction off the `convertibleBaseAsset` accumulated in `RiskFund`. The `convertibleBaseAsset`\n * is auctioned in exchange for users paying off the pool's bad debt. An auction can be started by anyone once a pool's bad debt has reached a minimum value.\n * This value is set and can be changed by the authorized accounts. If the pool’s bad debt exceeds the risk fund plus a 10% incentive, then the auction winner\n * is determined by who will pay off the largest percentage of the pool's bad debt. The auction winner then exchanges for the entire risk fund. Otherwise,\n * if the risk fund covers the pool's bad debt plus the 10% incentive, then the auction winner is determined by who will take the smallest percentage of the\n * risk fund in exchange for paying off all the pool's bad debt.\n */\ncontract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGuardUpgradeable, TokenDebtTracker {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Type of auction\n enum AuctionType {\n LARGE_POOL_DEBT,\n LARGE_RISK_FUND\n }\n\n /// @notice Status of auction\n enum AuctionStatus {\n NOT_STARTED,\n STARTED,\n ENDED\n }\n\n /// @notice Auction metadata\n struct Auction {\n uint256 startBlock;\n AuctionType auctionType;\n AuctionStatus status;\n VToken[] markets;\n uint256 seizedRiskFund;\n address highestBidder;\n uint256 highestBidBps;\n uint256 highestBidBlock;\n uint256 startBidBps;\n mapping(VToken => uint256) marketDebt;\n mapping(VToken => uint256) bidAmount;\n }\n\n /// @dev Max basis points i.e., 100%\n uint256 private constant MAX_BPS = 10000;\n\n uint256 private constant DEFAULT_NEXT_BIDDER_BLOCK_LIMIT = 100;\n\n uint256 private constant DEFAULT_WAIT_FOR_FIRST_BIDDER = 100;\n\n uint256 private constant DEFAULT_INCENTIVE_BPS = 1000; // 10%\n\n /// @notice Pool registry address\n address public poolRegistry;\n\n /// @notice Risk fund address\n IRiskFund public riskFund;\n\n /// @notice Minimum USD debt in pool for shortfall to trigger\n uint256 public minimumPoolBadDebt;\n\n /// @notice Incentive to auction participants, initial value set to 1000 or 10%\n uint256 public incentiveBps;\n\n /// @notice Time to wait for next bidder. Initially waits for 100 blocks\n uint256 public nextBidderBlockLimit;\n\n /// @notice Boolean of if auctions are paused\n bool public auctionsPaused;\n\n /// @notice Time to wait for first bidder. Initially waits for 100 blocks\n uint256 public waitForFirstBidder;\n\n /// @notice Auctions for each pool\n mapping(address => Auction) public auctions;\n\n /// @notice Emitted when a auction starts\n event AuctionStarted(\n address indexed comptroller,\n uint256 auctionStartBlock,\n AuctionType auctionType,\n VToken[] markets,\n uint256[] marketsDebt,\n uint256 seizedRiskFund,\n uint256 startBidBps\n );\n\n /// @notice Emitted when a bid is placed\n event BidPlaced(address indexed comptroller, uint256 auctionStartBlock, uint256 bidBps, address indexed bidder);\n\n /// @notice Emitted when a auction is completed\n event AuctionClosed(\n address indexed comptroller,\n uint256 auctionStartBlock,\n address indexed highestBidder,\n uint256 highestBidBps,\n uint256 seizedRiskFind,\n VToken[] markets,\n uint256[] marketDebt\n );\n\n /// @notice Emitted when a auction is restarted\n event AuctionRestarted(address indexed comptroller, uint256 auctionStartBlock);\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when minimum pool bad debt is updated\n event MinimumPoolBadDebtUpdated(uint256 oldMinimumPoolBadDebt, uint256 newMinimumPoolBadDebt);\n\n /// @notice Emitted when wait for first bidder block count is updated\n event WaitForFirstBidderUpdated(uint256 oldWaitForFirstBidder, uint256 newWaitForFirstBidder);\n\n /// @notice Emitted when next bidder block limit is updated\n event NextBidderBlockLimitUpdated(uint256 oldNextBidderBlockLimit, uint256 newNextBidderBlockLimit);\n\n /// @notice Emitted when incentiveBps is updated\n event IncentiveBpsUpdated(uint256 oldIncentiveBps, uint256 newIncentiveBps);\n\n /// @notice Emitted when auctions are paused\n event AuctionsPaused(address sender);\n\n /// @notice Emitted when auctions are unpaused\n event AuctionsResumed(address sender);\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 /**\n * @notice Initialize the shortfall contract\n * @param riskFund_ RiskFund contract address\n * @param minimumPoolBadDebt_ Minimum bad debt in base asset for a pool to start auction\n * @param accessControlManager_ AccessControlManager contract address\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when risk fund address is zero\n */\n function initialize(\n IRiskFund riskFund_,\n uint256 minimumPoolBadDebt_,\n address accessControlManager_\n ) external initializer {\n ensureNonzeroAddress(address(riskFund_));\n require(minimumPoolBadDebt_ != 0, \"invalid minimum pool bad debt\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n __ReentrancyGuard_init();\n __TokenDebtTracker_init();\n minimumPoolBadDebt = minimumPoolBadDebt_;\n riskFund = riskFund_;\n waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER;\n nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_LIMIT;\n incentiveBps = DEFAULT_INCENTIVE_BPS;\n auctionsPaused = false;\n }\n\n /**\n * @notice Place a bid greater than the previous in an ongoing auction\n * @param comptroller Comptroller address of the pool\n * @param bidBps The bid percent of the risk fund or bad debt depending on auction type\n * @param auctionStartBlock The block number when auction started\n * @custom:event Emits BidPlaced event on success\n */\n function placeBid(address comptroller, uint256 bidBps, uint256 auctionStartBlock) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(auction.startBlock == auctionStartBlock, \"auction has been restarted\");\n require(_isStarted(auction), \"no on-going auction\");\n require(!_isStale(auction), \"auction is stale, restart it\");\n require(bidBps > 0, \"basis points cannot be zero\");\n require(bidBps <= MAX_BPS, \"basis points cannot be more than 10000\");\n require(\n (auction.auctionType == AuctionType.LARGE_POOL_DEBT &&\n ((auction.highestBidder != address(0) && bidBps > auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps >= auction.startBidBps))) ||\n (auction.auctionType == AuctionType.LARGE_RISK_FUND &&\n ((auction.highestBidder != address(0) && bidBps < auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps <= auction.startBidBps))),\n \"your bid is not the highest\"\n );\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n if (auction.highestBidder != address(0)) {\n _transferOutOrTrackDebt(erc20, auction.highestBidder, auction.bidAmount[auction.markets[i]]);\n }\n uint256 balanceBefore = erc20.balanceOf(address(this));\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n uint256 currentBidAmount = ((auction.marketDebt[auction.markets[i]] * bidBps) / MAX_BPS);\n erc20.safeTransferFrom(msg.sender, address(this), currentBidAmount);\n } else {\n erc20.safeTransferFrom(msg.sender, address(this), auction.marketDebt[auction.markets[i]]);\n }\n\n uint256 balanceAfter = erc20.balanceOf(address(this));\n auction.bidAmount[auction.markets[i]] = balanceAfter - balanceBefore;\n }\n\n auction.highestBidder = msg.sender;\n auction.highestBidBps = bidBps;\n auction.highestBidBlock = block.number;\n\n emit BidPlaced(comptroller, auction.startBlock, bidBps, msg.sender);\n }\n\n /**\n * @notice Close an auction\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionClosed event on successful close\n */\n function closeAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(_isStarted(auction), \"no on-going auction\");\n require(\n block.number > auction.highestBidBlock + nextBidderBlockLimit && auction.highestBidder != address(0),\n \"waiting for next bidder. cannot close auction\"\n );\n\n uint256 marketsCount = auction.markets.length;\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n\n auction.status = AuctionStatus.ENDED;\n\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n uint256 balanceBefore = erc20.balanceOf(address(auction.markets[i]));\n erc20.safeTransfer(address(auction.markets[i]), auction.bidAmount[auction.markets[i]]);\n uint256 balanceAfter = erc20.balanceOf(address(auction.markets[i]));\n marketsDebt[i] = balanceAfter - balanceBefore;\n\n auction.markets[i].badDebtRecovered(marketsDebt[i]);\n }\n\n uint256 riskFundBidAmount;\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n riskFundBidAmount = auction.seizedRiskFund;\n } else {\n riskFundBidAmount = (auction.seizedRiskFund * auction.highestBidBps) / MAX_BPS;\n }\n\n address convertibleBaseAsset = riskFund.convertibleBaseAsset();\n\n uint256 transferredAmount = riskFund.transferReserveForAuction(comptroller, riskFundBidAmount);\n _transferOutOrTrackDebt(IERC20Upgradeable(convertibleBaseAsset), auction.highestBidder, riskFundBidAmount);\n\n emit AuctionClosed(\n comptroller,\n auction.startBlock,\n auction.highestBidder,\n auction.highestBidBps,\n transferredAmount,\n auction.markets,\n marketsDebt\n );\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionStarted event on success\n * @custom:event Errors if auctions are paused\n */\n function startAuction(address comptroller) external nonReentrant {\n require(!auctionsPaused, \"Auctions are paused\");\n _startAuction(comptroller);\n }\n\n /**\n * @notice Restart an auction\n * @param comptroller Address of the pool\n * @custom:event Emits AuctionRestarted event on successful restart\n */\n function restartAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(!auctionsPaused, \"auctions are paused\");\n require(_isStarted(auction), \"no on-going auction\");\n require(_isStale(auction), \"you need to wait for more time for first bidder\");\n\n auction.status = AuctionStatus.ENDED;\n\n emit AuctionRestarted(comptroller, auction.startBlock);\n _startAuction(comptroller);\n }\n\n /**\n * @notice Update next bidder block limit which is used determine when an auction can be closed\n * @param _nextBidderBlockLimit New next bidder block limit\n * @custom:event Emits NextBidderBlockLimitUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateNextBidderBlockLimit(uint256 _nextBidderBlockLimit) external {\n _checkAccessAllowed(\"updateNextBidderBlockLimit(uint256)\");\n require(_nextBidderBlockLimit != 0, \"_nextBidderBlockLimit must not be 0\");\n uint256 oldNextBidderBlockLimit = nextBidderBlockLimit;\n nextBidderBlockLimit = _nextBidderBlockLimit;\n emit NextBidderBlockLimitUpdated(oldNextBidderBlockLimit, _nextBidderBlockLimit);\n }\n\n /**\n * @notice Updates the incentive BPS\n * @param _incentiveBps New incentive BPS\n * @custom:event Emits IncentiveBpsUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateIncentiveBps(uint256 _incentiveBps) external {\n _checkAccessAllowed(\"updateIncentiveBps(uint256)\");\n require(_incentiveBps != 0, \"incentiveBps must not be 0\");\n uint256 oldIncentiveBps = incentiveBps;\n incentiveBps = _incentiveBps;\n emit IncentiveBpsUpdated(oldIncentiveBps, _incentiveBps);\n }\n\n /**\n * @notice Update minimum pool bad debt to start auction\n * @param _minimumPoolBadDebt Minimum bad debt in the base asset for a pool to start auction\n * @custom:event Emits MinimumPoolBadDebtUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateMinimumPoolBadDebt(uint256 _minimumPoolBadDebt) external {\n _checkAccessAllowed(\"updateMinimumPoolBadDebt(uint256)\");\n uint256 oldMinimumPoolBadDebt = minimumPoolBadDebt;\n minimumPoolBadDebt = _minimumPoolBadDebt;\n emit MinimumPoolBadDebtUpdated(oldMinimumPoolBadDebt, _minimumPoolBadDebt);\n }\n\n /**\n * @notice Update wait for first bidder block count. If the first bid is not made within this limit, the auction is closed and needs to be restarted\n * @param _waitForFirstBidder New wait for first bidder block count\n * @custom:event Emits WaitForFirstBidderUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateWaitForFirstBidder(uint256 _waitForFirstBidder) external {\n _checkAccessAllowed(\"updateWaitForFirstBidder(uint256)\");\n uint256 oldWaitForFirstBidder = waitForFirstBidder;\n waitForFirstBidder = _waitForFirstBidder;\n emit WaitForFirstBidderUpdated(oldWaitForFirstBidder, _waitForFirstBidder);\n }\n\n /**\n * @notice Update the pool registry this shortfall supports\n * @dev After Pool Registry is deployed we need to set the pool registry address\n * @param poolRegistry_ Address of pool registry contract\n * @custom:event Emits PoolRegistryUpdated on success\n * @custom:access Restricted to owner\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function updatePoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Pause auctions. This disables starting new auctions but lets the current auction finishes\n * @custom:event Emits AuctionsPaused on success\n * @custom:error Errors is auctions are paused\n * @custom:access Restricted by ACM\n */\n function pauseAuctions() external {\n _checkAccessAllowed(\"pauseAuctions()\");\n require(!auctionsPaused, \"Auctions are already paused\");\n auctionsPaused = true;\n emit AuctionsPaused(msg.sender);\n }\n\n /**\n * @notice Resume paused auctions.\n * @custom:event Emits AuctionsResumed on success\n * @custom:error Errors is auctions are active\n * @custom:access Restricted by ACM\n */\n function resumeAuctions() external {\n _checkAccessAllowed(\"resumeAuctions()\");\n require(auctionsPaused, \"Auctions are not paused\");\n auctionsPaused = false;\n emit AuctionsResumed(msg.sender);\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n */\n function _startAuction(address comptroller) internal {\n PoolRegistryInterface.VenusPool memory pool = PoolRegistry(poolRegistry).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n\n Auction storage auction = auctions[comptroller];\n require(\n auction.status == AuctionStatus.NOT_STARTED || auction.status == AuctionStatus.ENDED,\n \"auction is on-going\"\n );\n\n auction.highestBidBps = 0;\n auction.highestBidBlock = 0;\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = auction.markets[i];\n auction.marketDebt[vToken] = 0;\n }\n\n delete auction.markets;\n\n VToken[] memory vTokens = _getAllMarkets(comptroller);\n marketsCount = vTokens.length;\n ResilientOracleInterface priceOracle = _getPriceOracle(comptroller);\n uint256 poolBadDebt;\n\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n auction.markets = new VToken[](marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n uint256 marketBadDebt = vTokens[i].badDebt();\n\n priceOracle.updatePrice(address(vTokens[i]));\n uint256 usdValue = (priceOracle.getUnderlyingPrice(address(vTokens[i])) * marketBadDebt) / EXP_SCALE;\n\n poolBadDebt = poolBadDebt + usdValue;\n auction.markets[i] = vTokens[i];\n auction.marketDebt[vTokens[i]] = marketBadDebt;\n marketsDebt[i] = marketBadDebt;\n }\n\n require(poolBadDebt >= minimumPoolBadDebt, \"pool bad debt is too low\");\n\n priceOracle.updateAssetPrice(riskFund.convertibleBaseAsset());\n uint256 riskFundBalance = (priceOracle.getPrice(riskFund.convertibleBaseAsset()) *\n riskFund.getPoolsBaseAssetReserves(comptroller)) / EXP_SCALE;\n uint256 remainingRiskFundBalance = riskFundBalance;\n uint256 badDebtPlusIncentive = poolBadDebt + ((poolBadDebt * incentiveBps) / MAX_BPS);\n if (badDebtPlusIncentive >= riskFundBalance) {\n auction.startBidBps =\n (MAX_BPS * MAX_BPS * remainingRiskFundBalance) /\n (poolBadDebt * (MAX_BPS + incentiveBps));\n remainingRiskFundBalance = 0;\n auction.auctionType = AuctionType.LARGE_POOL_DEBT;\n } else {\n uint256 maxSeizeableRiskFundBalance = badDebtPlusIncentive;\n\n remainingRiskFundBalance = remainingRiskFundBalance - maxSeizeableRiskFundBalance;\n auction.auctionType = AuctionType.LARGE_RISK_FUND;\n auction.startBidBps = MAX_BPS;\n }\n\n auction.seizedRiskFund = riskFundBalance - remainingRiskFundBalance;\n auction.startBlock = block.number;\n auction.status = AuctionStatus.STARTED;\n auction.highestBidder = address(0);\n\n emit AuctionStarted(\n comptroller,\n auction.startBlock,\n auction.auctionType,\n auction.markets,\n marketsDebt,\n auction.seizedRiskFund,\n auction.startBidBps\n );\n }\n\n /**\n * @dev Returns the price oracle of the pool\n * @param comptroller Address of the pool's comptroller\n * @return oracle The pool's price oracle\n */\n function _getPriceOracle(address comptroller) internal view returns (ResilientOracleInterface) {\n return ResilientOracleInterface(ComptrollerViewInterface(comptroller).oracle());\n }\n\n /**\n * @dev Returns all markets of the pool\n * @param comptroller Address of the pool's comptroller\n * @return markets The pool's markets as VToken array\n */\n function _getAllMarkets(address comptroller) internal view returns (VToken[] memory) {\n return ComptrollerInterface(comptroller).getAllMarkets();\n }\n\n /**\n * @dev Checks if the auction has started\n * @param auction The auction to query the status for\n * @return True if the auction has started\n */\n function _isStarted(Auction storage auction) internal view returns (bool) {\n return auction.status == AuctionStatus.STARTED;\n }\n\n /**\n * @dev Checks if the auction is stale, i.e. there's no bidder and the auction\n * was started more than waitForFirstBidder blocks ago.\n * @param auction The auction to query the status for\n * @return True if the auction is stale\n */\n function _isStale(Auction storage auction) internal view returns (bool) {\n bool noBidder = auction.highestBidder == address(0);\n return noBidder && (block.number > auction.startBlock + waitForFirstBidder);\n }\n}\n" + }, + "contracts/test/ComptrollerHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\ncontract ComptrollerHarness is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function harnessFastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n}\n\ncontract EchoTypesComptroller {\n function stringy(string memory s) public pure returns (string memory) {\n return s;\n }\n\n function addresses(address a) public pure returns (address) {\n return a;\n }\n\n function booly(bool b) public pure returns (bool) {\n return b;\n }\n\n function listOInts(uint256[] memory u) public pure returns (uint256[] memory) {\n return u;\n }\n\n function reverty() public pure {\n require(false, \"gotcha sucka\");\n }\n}\n" + }, + "contracts/test/ComptrollerScenario.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\n\ncontract ComptrollerScenario is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function fastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n\n function unlist(VToken vToken) public {\n markets[address(vToken)].isListed = false;\n }\n\n function membershipLength(VToken vToken) public view returns (uint256) {\n return accountAssets[address(vToken)].length;\n }\n}\n" + }, + "contracts/test/ERC20.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeMath } from \"./SafeMath.sol\";\n\ninterface ERC20Base {\n event Approval(address indexed owner, address indexed spender, uint256 value);\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n function approve(address spender, uint256 value) external returns (bool);\n\n function totalSupply() external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function balanceOf(address who) external view returns (uint256);\n}\n\nabstract contract ERC20 is ERC20Base {\n function transfer(address to, uint256 value) external virtual returns (bool);\n\n function transferFrom(address from, address to, uint256 value) external virtual returns (bool);\n}\n\nabstract contract ERC20NS is ERC20Base {\n function transfer(address to, uint256 value) external virtual;\n\n function transferFrom(address from, address to, uint256 value) external virtual;\n}\n\n/**\n * @title Standard ERC20 token\n * @dev Implementation of the basic standard token.\n * See https://github.com/ethereum/EIPs/issues/20\n */\ncontract StandardToken is ERC20 {\n using SafeMath for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public override totalSupply;\n mapping(address => mapping(address => uint256)) public override allowance;\n mapping(address => uint256) public override balanceOf;\n\n constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external virtual override returns (bool) {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external virtual override returns (bool) {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n\n function approve(address _spender, uint256 amount) external virtual override returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\n/**\n * @title Non-Standard ERC20 token\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ncontract NonStandardToken is ERC20NS {\n using SafeMath for uint256;\n\n string public name;\n uint8 public decimals;\n string public symbol;\n uint256 public override totalSupply;\n mapping(address => mapping(address => uint256)) public override allowance;\n mapping(address => uint256) public override balanceOf;\n\n constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external override {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n }\n\n function transferFrom(address src, address dst, uint256 amount) external override {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n }\n\n function approve(address _spender, uint256 amount) external override returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\ncontract ERC20Harness is StandardToken {\n using SafeMath for uint256;\n // To support testing, we can specify addresses for which transferFrom should fail and return false\n mapping(address => bool) public failTransferFromAddresses;\n\n // To support testing, we allow the contract to always fail `transfer`.\n mapping(address => bool) public failTransferToAddresses;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function transfer(address dst, uint256 amount) external override returns (bool success) {\n // Added for testing purposes\n if (failTransferToAddresses[dst]) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool success) {\n // Added for testing purposes\n if (failTransferFromAddresses[src]) {\n return false;\n }\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n\n function harnessSetFailTransferFromAddress(address src, bool _fail) public {\n failTransferFromAddresses[src] = _fail;\n }\n\n function harnessSetFailTransferToAddress(address dst, bool _fail) public {\n failTransferToAddresses[dst] = _fail;\n }\n\n function harnessSetBalance(address _account, uint256 _amount) public {\n balanceOf[_account] = _amount;\n }\n}\n" + }, + "contracts/test/EvilToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { FaucetToken } from \"./FaucetToken.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title The Compound Evil Test Token\n * @author Compound\n * @notice A simple test token that fails certain operations\n */\ncontract EvilToken is FaucetToken {\n using SafeMath for uint256;\n\n bool public fail;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n fail = true;\n }\n\n function setFail(bool _fail) external {\n fail = _fail;\n }\n\n function transfer(address dst, uint256 amount) external override returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/FaucetToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { StandardToken, NonStandardToken } from \"./ERC20.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title The Compound Faucet Test Token\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetToken is StandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Compound Faucet Test Token (non-standard)\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetNonStandardToken is NonStandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n NonStandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Compound Faucet Re-Entrant Test Token\n * @author Compound\n * @notice A test token that is malicious and tries to re-enter callers\n */\ncontract FaucetTokenReEntrantHarness {\n using SafeMath for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 private totalSupply_;\n mapping(address => mapping(address => uint256)) private allowance_;\n mapping(address => uint256) private balanceOf_;\n\n bytes public reEntryCallData;\n string public reEntryFun;\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n modifier reEnter(string memory funName) {\n string memory _reEntryFun = reEntryFun;\n if (compareStrings(_reEntryFun, funName)) {\n reEntryFun = \"\"; // Clear re-entry fun\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = msg.sender.call(reEntryCallData);\n // solhint-disable-next-line no-inline-assembly\n assembly {\n if eq(success, 0) {\n revert(add(returndata, 0x20), returndatasize())\n }\n }\n }\n\n _;\n }\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n bytes memory _reEntryCallData,\n string memory _reEntryFun\n ) {\n totalSupply_ = _initialAmount;\n balanceOf_[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n reEntryCallData = _reEntryCallData;\n reEntryFun = _reEntryFun;\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf_[_owner] += value;\n totalSupply_ += value;\n emit Transfer(address(this), _owner, value);\n }\n\n function totalSupply() public reEnter(\"totalSupply\") returns (uint256) {\n return totalSupply_;\n }\n\n function allowance(address owner, address spender) public reEnter(\"allowance\") returns (uint256 remaining) {\n return allowance_[owner][spender];\n }\n\n function approve(address spender, uint256 amount) public reEnter(\"approve\") returns (bool success) {\n _approve(msg.sender, spender, amount);\n return true;\n }\n\n function balanceOf(address owner) public reEnter(\"balanceOf\") returns (uint256 balance) {\n return balanceOf_[owner];\n }\n\n function transfer(address dst, uint256 amount) public reEnter(\"transfer\") returns (bool success) {\n _transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) public reEnter(\"transferFrom\") returns (bool success) {\n _transfer(src, dst, amount);\n _approve(src, msg.sender, allowance_[src][msg.sender].sub(amount));\n return true;\n }\n\n function _approve(address owner, address spender, uint256 amount) internal {\n require(spender != address(0), \"FaucetToken: approve to the zero address\");\n require(owner != address(0), \"FaucetToken: approve from the zero address\");\n allowance_[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n function _transfer(address src, address dst, uint256 amount) internal {\n require(dst != address(0), \"FaucetToken: transfer to the zero address\");\n balanceOf_[src] = balanceOf_[src].sub(amount);\n balanceOf_[dst] = balanceOf_[dst].add(amount);\n emit Transfer(src, dst, amount);\n }\n\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)));\n }\n}\n" + }, + "contracts/test/FeeToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { FaucetToken } from \"./FaucetToken.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title Fee Token\n * @author Compound\n * @notice A simple test token that charges fees on transfer. Used to mock USDT.\n */\ncontract FeeToken is FaucetToken {\n using SafeMath for uint256;\n\n uint256 public basisPointFee;\n address public owner;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n uint256 _basisPointFee,\n address _owner\n ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n basisPointFee = _basisPointFee;\n owner = _owner;\n }\n\n function transfer(address dst, uint256 amount) public override returns (bool) {\n uint256 fee = amount.mul(basisPointFee).div(10000);\n uint256 net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) public override returns (bool) {\n uint256 fee = amount.mul(basisPointFee).div(10000);\n uint256 net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/HarnessMaxLoopsLimitHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\n\ncontract HarnessMaxLoopsLimitHelper is MaxLoopsLimitHelper {\n function setMaxLoopsLimit(uint256 limit) external {\n _setMaxLoopsLimit(limit);\n }\n\n function ensureMaxLoops(uint256 limit) external view {\n _ensureMaxLoops(limit);\n }\n}\n" + }, + "contracts/test/lib/ApproveOrRevertHarness.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ApproveOrRevert } from \"../../lib/ApproveOrRevert.sol\";\n\ncontract ApproveOrRevertHarness {\n using ApproveOrRevert for IERC20Upgradeable;\n\n function approve(IERC20Upgradeable token, address spender, uint256 amount) external {\n token.approveOrRevert(spender, amount);\n }\n}\n" + }, + "contracts/test/lib/TokenDebtTrackerHarness.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { TokenDebtTracker } from \"../../lib/TokenDebtTracker.sol\";\n\ncontract TokenDebtTrackerHarness is TokenDebtTracker {\n function initialize() external initializer {\n __TokenDebtTracker_init();\n }\n\n function addTokenDebt(IERC20Upgradeable token, address user, uint256 amount) external {\n tokenDebt[token][user] += amount;\n totalTokenDebt[token] += amount;\n }\n\n function transferOutOrTrackDebt(IERC20Upgradeable token, address user, uint256 amount) external {\n _transferOutOrTrackDebt(token, user, amount);\n }\n\n function transferOutOrTrackDebtSkippingBalanceCheck(\n IERC20Upgradeable token,\n address user,\n uint256 amount\n ) external {\n _transferOutOrTrackDebtSkippingBalanceCheck(token, user, amount);\n }\n}\n" + }, + "contracts/test/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 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(address from, address to, uint256 value) 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(address owner, address spender, uint256 value) private {\n allowance[owner][spender] = value;\n emit Approval(owner, spender, value);\n }\n\n function _transfer(address from, address to, uint256 value) 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/MockPriceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { BinanceOracle } from \"@venusprotocol/oracle/contracts/oracles/BinanceOracle.sol\";\nimport { ChainlinkOracle } from \"@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol\";\nimport { ProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/ProtocolReserve/ProtocolShareReserve.sol\";\nimport { VToken } from \"../../VToken.sol\";\n\ncontract MockPriceOracle is ResilientOracleInterface {\n mapping(address => uint256) public assetPrices;\n\n //set price in 6 decimal precision\n // solhint-disable-next-line no-empty-blocks\n constructor() {}\n\n function setPrice(address asset, uint256 price) external {\n assetPrices[asset] = price;\n }\n\n // solhint-disable-next-line no-empty-blocks\n function updatePrice(address vToken) external override {}\n\n // solhint-disable-next-line no-empty-blocks\n function updateAssetPrice(address asset) external override {}\n\n function getPrice(address asset) external view returns (uint256) {\n return assetPrices[asset];\n }\n\n //https://compound.finance/docs/prices\n function getUnderlyingPrice(address vToken) public view override returns (uint256) {\n return assetPrices[VToken(vToken).underlying()];\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(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/test/SafeMath.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\n// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol\n// Subject to the MIT license.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c;\n unchecked {\n c = a + b;\n }\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n uint256 c;\n unchecked {\n c = a + b;\n }\n require(c >= a, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction underflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c;\n unchecked {\n c = a * b;\n }\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c;\n unchecked {\n c = a * b;\n }\n require(c / a == b, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers.\n * Reverts on division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers.\n * Reverts with custom message on division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "contracts/test/UpgradedVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\n/**\n * @title Venus's VToken Contract\n * @notice VTokens which wrap an EIP-20 underlying and are immutable\n * @author Venus\n */\ncontract UpgradedVToken is VToken {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param riskManagement Addresses of risk fund contracts\n */\n\n /// @notice We added this new function to test contract upgrade\n function version() external pure returns (uint256) {\n return 2;\n }\n\n function initializeV2(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) public reinitializer(2) {\n super._initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\n );\n }\n\n function getTokenUnderlying() public view returns (address) {\n return underlying;\n }\n}\n" + }, + "contracts/test/VTokenHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\ncontract VTokenHarness is VToken {\n uint256 public blockNumber;\n uint256 public harnessExchangeRate;\n bool public harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function harnessSetAccrualBlockNumber(uint256 accrualBlockNumber_) external {\n accrualBlockNumber = accrualBlockNumber_;\n }\n\n function harnessSetBlockNumber(uint256 newBlockNumber) external {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint256 blocks) external {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint256 amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetTotalSupply(uint256 totalSupply_) external {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint256 totalBorrows_) external {\n totalBorrows = totalBorrows_;\n }\n\n function harnessSetTotalReserves(uint256 totalReserves_) external {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint256 totalSupply_, uint256 totalBorrows_, uint256 totalReserves_) external {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint256 exchangeRate) external {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address to_, bool fail_) external {\n failTransferToAddresses[to_] = fail_;\n }\n\n function harnessMintFresh(address account, uint256 mintAmount) external {\n super._mintFresh(account, account, mintAmount);\n }\n\n function harnessRedeemFresh(address payable account, uint256 vTokenAmount, uint256 underlyingAmount) external {\n super._redeemFresh(account, vTokenAmount, underlyingAmount);\n }\n\n function harnessSetAccountBorrows(address account, uint256 principal, uint256 interestIndex) external {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint256 borrowIndex_) external {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint256 borrowAmount) external {\n _borrowFresh(account, borrowAmount);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint256 repayAmount) external {\n _repayBorrowFresh(payer, account, repayAmount);\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VToken vTokenCollateral,\n bool skipLiquidityCheck\n ) external {\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n function harnessReduceReservesFresh(uint256 spreadAmount) external {\n return _reduceReservesFresh(spreadAmount);\n }\n\n function harnessSetReserveFactorFresh(uint256 newReserveFactorMantissa) external {\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) external {\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessAccountBorrows(address account) external view returns (uint256 principal, uint256 interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function getBorrowRateMaxMantissa() external pure returns (uint256) {\n return MAX_BORROW_RATE_MANTISSA;\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModel(newInterestRateModelAddress);\n }\n\n function harnessCallPreBorrowHook(uint256 amount) public {\n comptroller.preBorrowHook(address(this), msg.sender, amount);\n }\n\n function _doTransferOut(address to, uint256 amount) internal override {\n require(failTransferToAddresses[to] == false, \"HARNESS_TOKEN_TRANSFER_OUT_FAILED\");\n return super._doTransferOut(to, amount);\n }\n\n function _exchangeRateStored() internal view override returns (uint256) {\n if (harnessExchangeRateStored) {\n return harnessExchangeRate;\n }\n return super._exchangeRateStored();\n }\n\n function _getBlockNumber() internal view override returns (uint256) {\n return blockNumber;\n }\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n /**\n * Reentrancy Guard **\n */\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\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 /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\n );\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\n return true;\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\n return totalBorrows;\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\n _redeemFresh(msg.sender, redeemTokens, 0);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\n _redeemFresh(msg.sender, 0, redeemAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n _borrowFresh(msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @dev Gracefully return if reserves already reduced in accrueInterest\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n if (reduceReservesBlockNumber == _getBlockNumber()) return;\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\n }\n\n /**\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve\n * @param _newReduceReservesBlockDelta block difference value\n * @custom:access Only Governance\n */\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockDelta) external {\n _checkAccessAllowed(\"setReduceReservesBlockDelta(uint256)\");\n require(_newReduceReservesBlockDelta > 0, \"Invalid Input\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockDelta);\n reduceReservesBlockDelta = _newReduceReservesBlockDelta;\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint256) {\n return transferAllowances[owner][spender];\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return amount The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint256) {\n return accountTokens[owner];\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return rate The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this v\n * @return rate The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\n return _exchangeRateStored();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number */\n uint256 currentBlockNumber = _getBlockNumber();\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n if (currentBlockNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentBlockNumber;\n _reduceReservesFresh(totalReservesNew);\n }\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return NO_ERROR;\n }\n\n /**\n * @notice User supplies assets into the market and receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param payer The address of the account which is sending the assets for supply\n * @param minter The address of the account which is supplying the assets\n * @param mintAmount The amount of the underlying asset to supply\n */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `_doTransferIn` for the minter and the mintAmount.\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\n\n /*\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n }\n\n /**\n * @notice User redeems vTokens in exchange for the underlying asset\n * @dev Assumes interest has already been accrued up to the current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n */\n function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\n\n /* If redeemTokensIn > 0: */\n if (redeemTokensIn > 0) {\n /*\n * We calculate the exchange rate and the amount of underlying to be redeemed:\n * redeemTokens = redeemTokensIn\n */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\n * On success, the vToken has redeemAmount less of cash.\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n _doTransferOut(redeemer, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n }\n\n /**\n * @notice Users borrow assets from the protocol to their own address\n * @param borrower User who borrows the assets\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the borrower and the borrowAmount.\n * On success, the vToken borrowAmount less of cash.\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n _doTransferOut(borrower, borrowAmount);\n\n /* We emit a Borrow event */\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\n }\n\n /**\n * @notice Borrows are repaid by another user (possibly the borrower).\n * @param payer the account paying off the borrow\n * @param borrower the account with the debt being payed off\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call _doTransferIn for the payer and the repayAmount\n * On success, the vToken holds an additional repayAmount of cash.\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\n\n /*\n * We calculate the new borrower and total borrow balances, failing on underflow:\n * accountBorrowsNew = accountBorrows - actualRepayAmount\n * totalBorrowsNew = totalBorrows - actualRepayAmount\n */\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == NO_ERROR, \"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\");\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"LIQUIDATE_SEIZE_TOO_MUCH\");\n\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\n\n /*\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\n */\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\n ComptrollerInterface oldComptroller = comptroller;\n // Ensure invoke comptroller.isComptroller() returns true\n require(newComptroller.isComptroller(), \"marker method returned false\");\n\n // Set market's comptroller to newComptroller\n comptroller = newComptroller;\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(oldComptroller, newComptroller);\n }\n\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n }\n\n /**\n * @notice Add reserves by transferring from caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n if (reduceAmount == 0) {\n return;\n }\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n totalReservesNew = totalReserves - reduceAmount;\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert SetInterestRateModelFreshCheck();\n }\n\n // Track the market's current interest rate model\n oldInterestRateModel = interestRateModel;\n\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\n require(newInterestRateModel.isInterestRateModel(), \"marker method returned false\");\n\n // Set the interest rate model to newInterestRateModel\n interestRateModel = newInterestRateModel;\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\n }\n\n /**\n * Safe Token **\n */\n\n /**\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n * @param from Sender of the underlying tokens\n * @param amount Amount of underlying to transfer\n * @return Actual amount received\n */\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n // Return the amount that was *actually* transferred\n return balanceAfter - balanceBefore;\n }\n\n /**\n * @dev Just a regular ERC-20 transfer, reverts on failure\n * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\n * @dev Called by both `transfer` and `transferFrom` internally\n * @param spender The address of the account performing the transfer\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param tokens The number of tokens to transfer\n */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\n if (spender == src) {\n startingAllowance = type(uint256).max;\n } else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under,over}flow */\n uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if necessary) */\n if (startingAllowance != type(uint256).max) {\n transferAllowances[src][spender] = allowanceNew;\n }\n\n /* We emit a Transfer event */\n emit Transfer(src, dst, tokens);\n }\n\n /**\n * @notice Initialize the money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n require(accrualBlockNumber == 0 && borrowIndex == 0, \"market may only be initialized once\");\n\n // Set initial exchange rate\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa > 0, \"initial exchange rate must be greater than zero.\");\n\n _setComptroller(comptroller_);\n\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\n accrualBlockNumber = _getBlockNumber();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on block number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying tokens owned by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n return IERC20Upgradeable(underlying).balanceOf(address(this));\n }\n\n /**\n * @dev Function to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n * @return Current block number\n */\n function _getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\n\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\n */\n if (borrowSnapshot.principal == 0) {\n return 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\n */\n struct BorrowSnapshot {\n uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\n\n /**\n * @notice EIP-20 token name for this token\n */\n string public name;\n\n /**\n * @notice EIP-20 token symbol for this token\n */\n string public symbol;\n\n /**\n * @notice EIP-20 token decimals for this token\n */\n uint8 public decimals;\n\n /**\n * @notice Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\n\n // Maximum borrow rate that can ever be applied (.0005% / block)\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n /**\n * @notice Contract which oversees inter-vToken operations\n */\n ComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\n InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\n\n /**\n * @notice delta block after which reserves will be reduced\n */\n uint256 public reduceReservesBlockDelta;\n\n /**\n * @notice last block number at which reserves were reduced\n */\n uint256 public reduceReservesBlockNumber;\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[48] private __gap;\n}\n\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the spread reserves are reduced\n */\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /**\n * @notice Event emitted when reduce reserves block delta is changed\n */\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\n\n /**\n * @notice Event emitted when liquidation reserves are reduced\n */\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/WhitePaperInterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { BLOCKS_PER_YEAR, EXP_SCALE, MANTISSA_ONE } from \"./lib/constants.sol\";\n\n/**\n * @title Compound's WhitePaperInterestRateModel Contract\n * @author Compound\n * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper\n */\ncontract WhitePaperInterestRateModel is InterestRateModel {\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public immutable multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public immutable baseRatePerBlock;\n\n event NewInterestParams(uint256 baseRatePerBlock, uint256 multiplierPerBlock);\n\n /**\n * @notice Construct an interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n */\n constructor(uint256 baseRatePerYear, uint256 multiplierPerYear) {\n baseRatePerBlock = baseRatePerYear / BLOCKS_PER_YEAR;\n multiplierPerBlock = multiplierPerYear / BLOCKS_PER_YEAR;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock);\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public view override returns (uint256) {\n uint256 ur = utilizationRate(cash, borrows, reserves, badDebt);\n return ((ur * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) public view override returns (uint256) {\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\n uint256 borrowRate = getBorrowRate(cash, borrows, reserves, badDebt);\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\n uint256 incomeToDistribute = borrows * rateToPool;\n uint256 supply = cash + borrows + badDebt - reserves;\n return incomeToDistribute / supply;\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @param badDebt The amount of badDebt in the market\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\n */\n function utilizationRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows and badDebt\n if ((borrows + badDebt) == 0) {\n return 0;\n }\n\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\n\n if (rate > EXP_SCALE) {\n rate = EXP_SCALE;\n }\n\n return rate;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/ethereum.json b/deployments/ethereum.json new file mode 100644 index 000000000..dd24474d9 --- /dev/null +++ b/deployments/ethereum.json @@ -0,0 +1,5 @@ +{ + "name": "ethereum", + "chainId": "1", + "contracts": {} +} diff --git a/deployments/sepolia.json b/deployments/sepolia.json new file mode 100644 index 000000000..e8005fd0b --- /dev/null +++ b/deployments/sepolia.json @@ -0,0 +1,17017 @@ +{ + "name": "sepolia", + "chainId": "11155111", + "contracts": { + "ComptrollerBeacon": { + "address": "0x6cE54143a88CC22500D49D744fb6535D66a8294F", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "implementation", + "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": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "ComptrollerImpl": { + "address": "0x9D7496EA4DF696FcD279076cF21EE400eE43d965", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistry_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum ComptrollerStorage.Action", + "name": "action", + "type": "uint8" + } + ], + "name": "ActionPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "BorrowCapExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedLessThanOrEqualTo", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "CollateralExceedsThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "ComptrollerMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "collateralToSeize", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "availableCollateral", + "type": "uint256" + } + ], + "name": "InsufficientCollateral", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientShortfall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCollateralFactor", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLiquidationThreshold", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "MarketAlreadyListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "MarketNotCollateral", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "MarketNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedGreaterThan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "MinimalCollateralViolated", + "type": "error" + }, + { + "inputs": [], + "name": "NonzeroBorrowBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PriceError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "SnapshotError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "SupplyCapExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "TooMuchRepay", + "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": [ + { + "internalType": "address", + "name": "expectedSender", + "type": "address" + }, + { + "internalType": "address", + "name": "actualSender", + "type": "address" + } + ], + "name": "UnexpectedSender", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ComptrollerStorage.Action", + "name": "action", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "pauseState", + "type": "bool" + } + ], + "name": "ActionPausedMarket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "IsForcedLiquidationEnabledUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketSupported", + "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": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBorrowCap", + "type": "uint256" + } + ], + "name": "NewBorrowCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationThresholdMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinLiquidatableCollateral", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "NewMinLiquidatableCollateral", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardsDistributor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + } + ], + "name": "NewRewardsDistributor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSupplyCap", + "type": "uint256" + } + ], + "name": "NewSupplyCap", + "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" + }, + { + "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": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum ComptrollerStorage.Action", + "name": "action", + "type": "uint8" + } + ], + "name": "actionPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract RewardsDistributor", + "name": "_rewardsDistributor", + "type": "address" + } + ], + "name": "addRewardsDistributor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllMarkets", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getBorrowingPower", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenModify", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "getHypotheticalAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRewardDistributors", + "outputs": [ + { + "internalType": "contract RewardsDistributor[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getRewardsByMarket", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplySpeed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowSpeed", + "type": "uint256" + } + ], + "internalType": "struct ComptrollerStorage.RewardSpeeds[]", + "name": "rewardSpeeds", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "healAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopLimit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "isMarketListed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract VToken", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "internalType": "struct ComptrollerStorage.LiquidationOrder[]", + "name": "orders", + "type": "tuple[]" + } + ], + "name": "liquidateAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensToSeize", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationThresholdMantissa", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minLiquidatableCollateral", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "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": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "preBorrowHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "skipLiquidityCheck", + "type": "bool" + } + ], + "name": "preLiquidateHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "preMintHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "preRedeemHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "preRepayHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "seizerContract", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "preSeizeHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "preTransferHook", + "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": "contract VToken[]", + "name": "marketsList", + "type": "address[]" + }, + { + "internalType": "enum ComptrollerStorage.Action[]", + "name": "actionsList", + "type": "uint8[]" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "setActionsPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "setCloseFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "setCollateralFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "setForcedLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "setLiquidationIncentive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "setMarketBorrowCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "setMarketSupplyCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newMinLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "setMinLiquidatableCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "newOracle", + "type": "address" + } + ], + "name": "setPriceOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "supportMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "updatePrices", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "Comptroller_Core": { + "address": "0x7Aa39ab4BcA897F403425C9C6FDbd0f882Be0D70", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "Comptroller_Curve": { + "address": "0xD298182D3ACb43e98e32757FF09C91F203e9E67E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "Comptroller_Stablecoins": { + "address": "0x18eF8D2bee415b731C25662568dc1035001cEB2c", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "DefaultProxyAdmin": { + "address": "0x01435866babd91311b1355cf3af488cca36db68e", + "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" + } + ] + }, + "JumpRateModelV2_base0bps_slope450bps_jump8000bps_kink8000bps": { + "address": "0xe948BBE16a846988A501A33Fb6A82Af4E2f231aE", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] + }, + "JumpRateModelV2_base0bps_slope500bps_jump8000bps_kink7500bps": { + "address": "0x1A9ca9032C7ee7335736fCaa5e8fb62b283538da", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] + }, + "JumpRateModelV2_base0bps_slope700bps_jump8000bps_kink8000bps": { + "address": "0xA03205bC635A772E533E7BE36b5701E331a70ea3", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] + }, + "JumpRateModelV2_base200bps_slope1500bps_jump30000bps_kink4500bps": { + "address": "0x710F4044007a0e72e54626394462dB57d2d8479F", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] + }, + "JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps": { + "address": "0xaf5feAbe347BE5DF603CE63e45155bDb8049C78c", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ] + }, + "MockCRV": { + "address": "0x2c78EF7eab67A6e0C9cAa6f2821929351bdDF3d3", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "MockUSDC": { + "address": "0x772d68929655ce7234C8C94256526ddA66Ef641E", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "MockUSDT": { + "address": "0x8d412FD0bc5d826615065B931171Eed10F5AF266", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "MockWBTC": { + "address": "0x92A2928f5634BEa89A195e7BeCF0f0FEEDAB885b", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "MockWETH": { + "address": "0x700868CAbb60e90d77B6588ce072d9859ec8E281", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "MockcrvUSD": { + "address": "0x36421d873abCa3E2bE6BB3c819C0CF26374F63b6", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "PoolLens": { + "address": "0xC319C2E53a5f732ebF0eb87b14F56B53bdc3446b", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + } + ], + "name": "getAllPools", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + }, + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "address", + "name": "priceOracle", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata[]", + "name": "vTokens", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.PoolData[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "comptrollerAddress", + "type": "address" + } + ], + "name": "getPendingRewards", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "distributorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "totalRewards", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.PendingReward[]", + "name": "pendingRewards", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.RewardSummary[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptrollerAddress", + "type": "address" + } + ], + "name": "getPoolBadDebt", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "totalBadDebtUsd", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "badDebtUsd", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.BadDebt[]", + "name": "badDebts", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.BadDebtSummary", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolByComptroller", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + }, + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "address", + "name": "priceOracle", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata[]", + "name": "vTokens", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.PoolData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "venusPool", + "type": "tuple" + } + ], + "name": "getPoolDataFromVenusPool", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + }, + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "address", + "name": "priceOracle", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata[]", + "name": "vTokens", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.PoolData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPoolsSupportedByAsset", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getVTokenForAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "vTokenBalances", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUnderlying", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenAllowance", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenBalances", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "vTokenBalancesAll", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUnderlying", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenAllowance", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenBalances[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "vTokenMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "vTokenMetadataAll", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "vTokenUnderlyingPrice", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "underlyingPrice", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenUnderlyingPrice", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "vTokenUnderlyingPriceAll", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "underlyingPrice", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenUnderlyingPrice[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "PoolRegistry": { + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", + "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": [ + { + "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": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "MarketAdded", + "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" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "oldMetadata", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "newMetadata", + "type": "tuple" + } + ], + "name": "PoolMetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "oldName", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newName", + "type": "string" + } + ], + "name": "PoolNameSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "pool", + "type": "tuple" + } + ], + "name": "PoolRegistered", + "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": [ + { + "components": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSupply", + "type": "uint256" + }, + { + "internalType": "address", + "name": "vTokenReceiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplyCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistry.AddMarketInput", + "name": "input", + "type": "tuple" + } + ], + "name": "addMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "contract Comptroller", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "addPool", + "outputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllPools", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolByComptroller", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPoolsSupportedByAsset", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getVTokenForAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getVenusPoolMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "metadata", + "outputs": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "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": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "setPoolName", + "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" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "metadata_", + "type": "tuple" + } + ], + "name": "updatePoolMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "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" + } + ] + }, + "PoolRegistry_Implementation": { + "address": "0x3213607Db41319E32C3706116Adf1Ae890E4083A", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "MarketAdded", + "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" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "oldMetadata", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "newMetadata", + "type": "tuple" + } + ], + "name": "PoolMetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "oldName", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newName", + "type": "string" + } + ], + "name": "PoolNameSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "pool", + "type": "tuple" + } + ], + "name": "PoolRegistered", + "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": [ + { + "components": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSupply", + "type": "uint256" + }, + { + "internalType": "address", + "name": "vTokenReceiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplyCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistry.AddMarketInput", + "name": "input", + "type": "tuple" + } + ], + "name": "addMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "contract Comptroller", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "addPool", + "outputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllPools", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolByComptroller", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPoolsSupportedByAsset", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getVTokenForAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getVenusPoolMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "metadata", + "outputs": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "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": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "setPoolName", + "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" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "metadata_", + "type": "tuple" + } + ], + "name": "updatePoolMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "PoolRegistry_Proxy": { + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", + "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" + } + ] + }, + "RewardsDistributorImpl": { + "address": "0xaA0472719984e799aC11D01C16D3c6B0F8d5C39B", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAccrued", + "type": "uint256" + } + ], + "name": "ContributorRewardsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketInitialized", + "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": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "RewardTokenBorrowIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardTokenGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "RewardTokenSupplyIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenSupplySpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "SupplyLastRewardingBlockUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "INITIAL_INDEX", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "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": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "distributeBorrowerRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", + "type": "address" + } + ], + "name": "distributeSupplierRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "grantRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract Comptroller", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "initializeMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastContributorBlock", + "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": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenContributorSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardTokenSpeed", + "type": "uint256" + } + ], + "name": "setContributorRewardTokenSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" + } + ], + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "setRewardTokenSpeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + } + ], + "name": "updateContributorRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updateRewardTokenSupplyIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VTokenBeacon": { + "address": "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "implementation", + "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": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "VTokenImpl": { + "address": "0x3630AD592d07294aB37336b734aB053685dDD35c", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "actualAddAmount", + "type": "uint256" + } + ], + "name": "AddReservesFactorFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowCashNotAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "ForceLiquidateBorrowUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "HealBorrowUnauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "LiquidateAccrueCollateralInterestFailed", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsUintMax", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsZero", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCollateralFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateSeizeLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "MintFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "ProtocolSeizeShareTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemTransferOutNotPossible", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashNotAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashValidation", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RepayBorrowFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetInterestRateModelFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorBoundsCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "TransferNotAllowed", + "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": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" + } + ], + "name": "BadDebtIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" + } + ], + "name": "BadDebtRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "HealBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" + } + ], + "name": "Mint", + "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": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldProtocolSeizeShareMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa", + "type": "uint256" + } + ], + "name": "NewProtocolSeizeShare", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldShortfall", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newShortfall", + "type": "address" + } + ], + "name": "NewShortfallContract", + "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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ProtocolSeize", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "SpreadReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "NO_ERROR", + "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": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "addReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "badDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "recoveredAmount_", + "type": "uint256" + } + ], + "name": "badDebtRecovered", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "bool", + "name": "skipLiquidityCheck", + "type": "bool" + } + ], + "name": "forceLiquidateBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vTokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "healBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "shortfall", + "type": "address" + }, + { + "internalType": "address payable", + "name": "protocolShareReserve", + "type": "address" + } + ], + "internalType": "struct VTokenInterface.RiskManagementInit", + "name": "riskManagement", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "protocolSeizeShareMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "reduceReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "setInterestRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa_", + "type": "uint256" + } + ], + "name": "setProtocolSeizeShare", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "protocolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "setReserveFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "shortfall_", + "type": "address" + } + ], + "name": "setShortfallContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "VToken_vCRV_Core": { + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vCRV_Curve": { + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDC_Core": { + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDC_Stablecoins": { + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_Core": { + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vUSDT_Stablecoins": { + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vWBTC_Core": { + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vWETH_Core": { + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vcrvUSD_Core": { + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vcrvUSD_Curve": { + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "VToken_vcrvUSD_Stablecoins": { + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "BoundValidator": { + "address": "0x60c4Aa92eEb6884a76b309Dd8B3731ad514d6f9B", + "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": [], + "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": [ + { + "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": 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": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "upperBound", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "lowerBound", + "type": "uint256" + } + ], + "name": "ValidateConfigAdded", + "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": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" + } + ], + "internalType": "struct BoundValidator.ValidateConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "setValidateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" + } + ], + "internalType": "struct BoundValidator.ValidateConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "setValidateConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "validateConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "reportedPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "anchorPrice", + "type": "uint256" + } + ], + "name": "validatePriceWithAnchorPrice", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "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" + } + ] + }, + "BoundValidator_Implementation": { + "address": "0xcc633492097078Ae590C0d11924e82A23f3Ab3E2", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": 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": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "upperBound", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "lowerBound", + "type": "uint256" + } + ], + "name": "ValidateConfigAdded", + "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": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" + } + ], + "internalType": "struct BoundValidator.ValidateConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "setValidateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" + } + ], + "internalType": "struct BoundValidator.ValidateConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "setValidateConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "validateConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "upperBoundRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lowerBoundRatio", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "reportedPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "anchorPrice", + "type": "uint256" + } + ], + "name": "validatePriceWithAnchorPrice", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "BoundValidator_Proxy": { + "address": "0x60c4Aa92eEb6884a76b309Dd8B3731ad514d6f9B", + "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": [], + "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" + } + ] + }, + "ChainlinkOracle": { + "address": "0x102F0b714E5d321187A4b6E5993358448f7261cE", + "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": [], + "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": [ + { + "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": 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": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousPriceMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPriceMantissa", + "type": "uint256" + } + ], + "name": "PricePosted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "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": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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" + } + ], + "name": "prices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "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": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "name": "setDirectPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "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" + } + ] + }, + "ChainlinkOracle_Implementation": { + "address": "0x034Cc5097379B13d3Ed5F6c85c8FAf20F48aE480", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": 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": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousPriceMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPriceMantissa", + "type": "uint256" + } + ], + "name": "PricePosted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "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": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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" + } + ], + "name": "prices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "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": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "name": "setDirectPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "ChainlinkOracle_Proxy": { + "address": "0x102F0b714E5d321187A4b6E5993358448f7261cE", + "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": [], + "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" + } + ] + }, + "RedStoneOracle": { + "address": "0x4e6269Ef406B4CEE6e67BA5B5197c2FfD15099AE", + "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": [], + "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": [ + { + "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": 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": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousPriceMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPriceMantissa", + "type": "uint256" + } + ], + "name": "PricePosted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "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": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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" + } + ], + "name": "prices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "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": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "name": "setDirectPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "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" + } + ] + }, + "RedStoneOracle_Implementation": { + "address": "0x718299912d52c5720c70318B9dF418bc2520fb60", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": 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": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousPriceMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPriceMantissa", + "type": "uint256" + } + ], + "name": "PricePosted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "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": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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" + } + ], + "name": "prices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "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": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "name": "setDirectPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "RedStoneOracle_Proxy": { + "address": "0x4e6269Ef406B4CEE6e67BA5B5197c2FfD15099AE", + "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": [], + "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" + } + ] + }, + "ResilientOracle": { + "address": "0x8000eca36201dddf5805Aa4BeFD73d1EB4D23264", + "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": [], + "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": [ + { + "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": 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": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "role", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "OracleEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "OracleSet", + "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": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "mainOracle", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pivotOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "fallbackOracle", + "type": "address" + } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "INVALID_PRICE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "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": [], + "name": "boundValidator", + "outputs": [ + { + "internalType": "contract BoundValidatorInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "enableOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + } + ], + "name": "getOracle", + "outputs": [ + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getTokenConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "nativeMarket", + "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": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "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": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + } + ], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "updateAssetPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updatePrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vai", + "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" + } + ] + }, + "ResilientOracle_Implementation": { + "address": "0x86F82bca79774fc04859966917D2291A68b870A9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "nativeMarketAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "vaiAddress", + "type": "address" + }, + { + "internalType": "contract BoundValidatorInterface", + "name": "_boundValidator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": 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": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "role", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "OracleEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "OracleSet", + "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": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "mainOracle", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pivotOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "fallbackOracle", + "type": "address" + } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "INVALID_PRICE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "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": [], + "name": "boundValidator", + "outputs": [ + { + "internalType": "contract BoundValidatorInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "enableOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + } + ], + "name": "getOracle", + "outputs": [ + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getTokenConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "nativeMarket", + "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": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "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": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + } + ], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + } + ], + "internalType": "struct ResilientOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "updateAssetPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updatePrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vai", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + }, + "ResilientOracle_Proxy": { + "address": "0x8000eca36201dddf5805Aa4BeFD73d1EB4D23264", + "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": [], + "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" + } + ] + }, + "VTreasuryV8": { + "address": "0x4116CA92960dF77756aAAc3aFd91361dB657fbF8", + "abi": [ + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "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": false, + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "WithdrawTreasuryNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "WithdrawTreasuryToken", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "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": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawTreasuryNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawTreasuryToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] + } + } +} diff --git a/deployments/sepolia/.chainId b/deployments/sepolia/.chainId new file mode 100644 index 000000000..bd8d1cd44 --- /dev/null +++ b/deployments/sepolia/.chainId @@ -0,0 +1 @@ +11155111 \ No newline at end of file diff --git a/deployments/sepolia/ComptrollerBeacon.json b/deployments/sepolia/ComptrollerBeacon.json new file mode 100644 index 000000000..9e67dc2c2 --- /dev/null +++ b/deployments/sepolia/ComptrollerBeacon.json @@ -0,0 +1,206 @@ +{ + "address": "0x6cE54143a88CC22500D49D744fb6535D66a8294F", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "implementation", + "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": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x16972a044f796b46df07b6eee3c3d95b2755fca1cfa55fed89a857f9fac86775", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x6cE54143a88CC22500D49D744fb6535D66a8294F", + "transactionIndex": 31, + "gasUsed": "292181", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000004000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000010000000000000000000000000000000000020000000020000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x173e879999ef93a502cbdf626bdca83f9692ced30fd415be8e013c6926cd25d4", + "transactionHash": "0x16972a044f796b46df07b6eee3c3d95b2755fca1cfa55fed89a857f9fac86775", + "logs": [ + { + "transactionIndex": 31, + "blockNumber": 4776619, + "transactionHash": "0x16972a044f796b46df07b6eee3c3d95b2755fca1cfa55fed89a857f9fac86775", + "address": "0x6cE54143a88CC22500D49D744fb6535D66a8294F", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 36, + "blockHash": "0x173e879999ef93a502cbdf626bdca83f9692ced30fd415be8e013c6926cd25d4" + } + ], + "blockNumber": 4776619, + "cumulativeGasUsed": "3842478", + "status": 1, + "byzantium": true + }, + "args": ["0x9D7496EA4DF696FcD279076cF21EE400eE43d965"], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"implementation\",\"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\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their implementation contract, which is where they will delegate all function calls. An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\",\"events\":{\"Upgraded(address)\":{\"details\":\"Emitted when the implementation returned by the beacon is changed.\"}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the beacon.\"},\"implementation()\":{\"details\":\"Returns the current implementation address.\"},\"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. 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.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgradeTo(address)\":{\"details\":\"Upgrades the beacon to a new implementation. Emits an {Upgraded} event. Requirements: - msg.sender must be the owner of the contract. - `newImplementation` must be a contract.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol\":\"UpgradeableBeacon\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x6ec71aef5659f3f74011169948d2fcda8c6599be5bb38f986380a8737f96cc0f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506040516104e43803806104e483398101604081905261002f91610151565b61003833610047565b61004181610097565b50610181565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6100aa8161014260201b6101a01760201c565b6101205760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f60448201527f6e206973206e6f74206120636f6e747261637400000000000000000000000000606482015260840160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03163b151590565b60006020828403121561016357600080fd5b81516001600160a01b038116811461017a57600080fd5b9392505050565b610354806101906000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80633659cfe61461005c5780635c60da1b14610071578063715018a61461009a5780638da5cb5b146100a2578063f2fde38b146100b3575b600080fd5b61006f61006a3660046102ee565b6100c6565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006f61010e565b6000546001600160a01b031661007e565b61006f6100c13660046102ee565b610122565b6100ce6101af565b6100d781610209565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6101166101af565b610120600061029e565b565b61012a6101af565b6001600160a01b0381166101945760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019d8161029e565b50565b6001600160a01b03163b151590565b6000546001600160a01b031633146101205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161018b565b6001600160a01b0381163b61027c5760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b606482015260840161018b565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561030057600080fd5b81356001600160a01b038116811461031757600080fd5b939250505056fea2646970667358221220dbaafc37b41702e4f412c3196a46d19f8c0bba820e2f5b5f81b00307ad83d17064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80633659cfe61461005c5780635c60da1b14610071578063715018a61461009a5780638da5cb5b146100a2578063f2fde38b146100b3575b600080fd5b61006f61006a3660046102ee565b6100c6565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006f61010e565b6000546001600160a01b031661007e565b61006f6100c13660046102ee565b610122565b6100ce6101af565b6100d781610209565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6101166101af565b610120600061029e565b565b61012a6101af565b6001600160a01b0381166101945760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019d8161029e565b50565b6001600160a01b03163b151590565b6000546001600160a01b031633146101205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161018b565b6001600160a01b0381163b61027c5760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b606482015260840161018b565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561030057600080fd5b81356001600160a01b038116811461031757600080fd5b939250505056fea2646970667358221220dbaafc37b41702e4f412c3196a46d19f8c0bba820e2f5b5f81b00307ad83d17064736f6c634300080d0033", + "devdoc": { + "details": "This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their implementation contract, which is where they will delegate all function calls. An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.", + "events": { + "Upgraded(address)": { + "details": "Emitted when the implementation returned by the beacon is changed." + } + }, + "kind": "dev", + "methods": { + "constructor": { + "details": "Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the beacon." + }, + "implementation()": { + "details": "Returns the current implementation address." + }, + "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. 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." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgradeTo(address)": { + "details": "Upgrades the beacon to a new implementation. Emits an {Upgraded} event. Requirements: - msg.sender must be the owner of the contract. - `newImplementation` must be a contract." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1795, + "contract": "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol:UpgradeableBeacon", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 2375, + "contract": "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol:UpgradeableBeacon", + "label": "_implementation", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} diff --git a/deployments/sepolia/ComptrollerImpl.json b/deployments/sepolia/ComptrollerImpl.json new file mode 100644 index 000000000..82b8dad1d --- /dev/null +++ b/deployments/sepolia/ComptrollerImpl.json @@ -0,0 +1,2744 @@ +{ + "address": "0x9D7496EA4DF696FcD279076cF21EE400eE43d965", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistry_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum ComptrollerStorage.Action", + "name": "action", + "type": "uint8" + } + ], + "name": "ActionPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "BorrowCapExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedLessThanOrEqualTo", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "CollateralExceedsThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "ComptrollerMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "collateralToSeize", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "availableCollateral", + "type": "uint256" + } + ], + "name": "InsufficientCollateral", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientShortfall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCollateralFactor", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLiquidationThreshold", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "MarketAlreadyListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "MarketNotCollateral", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "MarketNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedGreaterThan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "MinimalCollateralViolated", + "type": "error" + }, + { + "inputs": [], + "name": "NonzeroBorrowBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PriceError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "SnapshotError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "SupplyCapExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "TooMuchRepay", + "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": [ + { + "internalType": "address", + "name": "expectedSender", + "type": "address" + }, + { + "internalType": "address", + "name": "actualSender", + "type": "address" + } + ], + "name": "UnexpectedSender", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum ComptrollerStorage.Action", + "name": "action", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "pauseState", + "type": "bool" + } + ], + "name": "ActionPausedMarket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "IsForcedLiquidationEnabledUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketSupported", + "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": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBorrowCap", + "type": "uint256" + } + ], + "name": "NewBorrowCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationThresholdMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinLiquidatableCollateral", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "NewMinLiquidatableCollateral", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardsDistributor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + } + ], + "name": "NewRewardsDistributor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSupplyCap", + "type": "uint256" + } + ], + "name": "NewSupplyCap", + "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" + }, + { + "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": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum ComptrollerStorage.Action", + "name": "action", + "type": "uint8" + } + ], + "name": "actionPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract RewardsDistributor", + "name": "_rewardsDistributor", + "type": "address" + } + ], + "name": "addRewardsDistributor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllMarkets", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getBorrowingPower", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenModify", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "getHypotheticalAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRewardDistributors", + "outputs": [ + { + "internalType": "contract RewardsDistributor[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getRewardsByMarket", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplySpeed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowSpeed", + "type": "uint256" + } + ], + "internalType": "struct ComptrollerStorage.RewardSpeeds[]", + "name": "rewardSpeeds", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "healAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopLimit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "isMarketListed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract VToken", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "internalType": "struct ComptrollerStorage.LiquidationOrder[]", + "name": "orders", + "type": "tuple[]" + } + ], + "name": "liquidateAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensToSeize", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationThresholdMantissa", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minLiquidatableCollateral", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "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": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "preBorrowHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "skipLiquidityCheck", + "type": "bool" + } + ], + "name": "preLiquidateHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "preMintHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "preRedeemHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "preRepayHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "seizerContract", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "preSeizeHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "preTransferHook", + "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": "contract VToken[]", + "name": "marketsList", + "type": "address[]" + }, + { + "internalType": "enum ComptrollerStorage.Action[]", + "name": "actionsList", + "type": "uint8[]" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "setActionsPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "setCloseFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "setCollateralFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "setForcedLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "setLiquidationIncentive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "setMarketBorrowCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "setMarketSupplyCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newMinLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "setMinLiquidatableCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "newOracle", + "type": "address" + } + ], + "name": "setPriceOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "supportMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "updatePrices", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xed96d238175ecb7fbcab2d5304d8116a7679c1f9f31969e0a1d918b0e778f852", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x9D7496EA4DF696FcD279076cF21EE400eE43d965", + "transactionIndex": 0, + "gasUsed": "4743383", + "logsBloom": "0x00000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000002000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000", + "blockHash": "0xc73cf23f22957dc2d103656faf4c1fe6c03da7a2f6994d4aec08a01882559e80", + "transactionHash": "0xed96d238175ecb7fbcab2d5304d8116a7679c1f9f31969e0a1d918b0e778f852", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 4776618, + "transactionHash": "0xed96d238175ecb7fbcab2d5304d8116a7679c1f9f31969e0a1d918b0e778f852", + "address": "0x9D7496EA4DF696FcD279076cF21EE400eE43d965", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", + "logIndex": 0, + "blockHash": "0xc73cf23f22957dc2d103656faf4c1fe6c03da7a2f6994d4aec08a01882559e80" + } + ], + "blockNumber": 4776618, + "cumulativeGasUsed": "4743383", + "status": 1, + "byzantium": true + }, + "args": ["0x758f5715d817e02857Ba40889251201A5aE3E186"], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum ComptrollerStorage.Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"ActionPaused\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"cap\",\"type\":\"uint256\"}],\"name\":\"BorrowCapExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedLessThanOrEqualTo\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"CollateralExceedsThreshold\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ComptrollerMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"collateralToSeize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"availableCollateral\",\"type\":\"uint256\"}],\"name\":\"InsufficientCollateral\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientShortfall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCollateralFactor\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidLiquidationThreshold\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"MarketNotCollateral\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expectedGreaterThan\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"MinimalCollateralViolated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonzeroBorrowBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PriceError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"SnapshotError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"cap\",\"type\":\"uint256\"}],\"name\":\"SupplyCapExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooMuchRepay\",\"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\":[{\"internalType\":\"address\",\"name\":\"expectedSender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"actualSender\",\"type\":\"address\"}],\"name\":\"UnexpectedSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enum ComptrollerStorage.Action\",\"name\":\"action\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPausedMarket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"IsForcedLiquidationEnabledUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketSupported\",\"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\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationThresholdMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationThreshold\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinLiquidatableCollateral\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinLiquidatableCollateral\",\"type\":\"uint256\"}],\"name\":\"NewMinLiquidatableCollateral\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardsDistributor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"}],\"name\":\"NewRewardsDistributor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSupplyCap\",\"type\":\"uint256\"}],\"name\":\"NewSupplyCap\",\"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\"},{\"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\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum ComptrollerStorage.Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract RewardsDistributor\",\"name\":\"_rewardsDistributor\",\"type\":\"address\"}],\"name\":\"addRewardsDistributor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getBorrowingPower\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRewardDistributors\",\"outputs\":[{\"internalType\":\"contract RewardsDistributor[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getRewardsByMarket\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"supplySpeed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowSpeed\",\"type\":\"uint256\"}],\"internalType\":\"struct ComptrollerStorage.RewardSpeeds[]\",\"name\":\"rewardSpeeds\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"healAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopLimit\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"accessControlManager\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"isMarketListed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract VToken\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct ComptrollerStorage.LiquidationOrder[]\",\"name\":\"orders\",\"type\":\"tuple[]\"}],\"name\":\"liquidateAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokensToSeize\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidationIncentiveMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThresholdMantissa\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLoopsLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minLiquidatableCollateral\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"preBorrowHook\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"skipLiquidityCheck\",\"type\":\"bool\"}],\"name\":\"preLiquidateHook\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"preMintHook\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"preRedeemHook\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"}],\"name\":\"preRepayHook\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"seizerContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"}],\"name\":\"preSeizeHook\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"preTransferHook\",\"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\":\"contract VToken[]\",\"name\":\"marketsList\",\"type\":\"address[]\"},{\"internalType\":\"enum ComptrollerStorage.Action[]\",\"name\":\"actionsList\",\"type\":\"uint8[]\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"name\":\"setActionsPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"setCloseFactor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"setCollateralFactor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"setForcedLiquidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"setLiquidationIncentive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketBorrowCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newSupplyCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketSupplyCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMinLiquidatableCollateral\",\"type\":\"uint256\"}],\"name\":\"setMinLiquidatableCollateral\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"supportMarket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action to check\",\"market\":\"vToken address\"},\"returns\":{\"_0\":\"paused True if the action is paused otherwise false\"}},\"addRewardsDistributor(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewRewardsDistributor with distributor address\",\"details\":\"Only callable by the admin\",\"params\":{\"_rewardsDistributor\":\"Address of the RewardDistributor contract to add\"}},\"checkMembership(address,address)\":{\"params\":{\"account\":\"The address of the account to check\",\"vToken\":\"The vToken to check\"},\"returns\":{\"_0\":\"True if the account is in the market specified, otherwise false.\"}},\"constructor\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"poolRegistry_\":\"Pool registry address\"}},\"enterMarkets(address[])\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ActionPaused error is thrown if entering any of the markets is pausedMarketNotListed error is thrown if any of the markets is not listed\",\"custom:event\":\"MarketEntered is emitted for each market on success\",\"params\":{\"vTokens\":\"The list of addresses of the vToken markets to be enabled\"},\"returns\":{\"_0\":\"errors An array of NO_ERROR for compatibility with Venus core tooling\"}},\"exitMarket(address)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ActionPaused error is thrown if exiting the market is pausedNonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this marketMarketNotListed error is thrown when the market is not listedInsufficientLiquidity error is thrown if exiting the market would lead to user's insolvencySnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset\",\"custom:event\":\"MarketExited is emitted on success\",\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow.\",\"params\":{\"vTokenAddress\":\"The address of the asset to be removed\"},\"returns\":{\"_0\":\"error Always NO_ERROR for compatibility with Venus core tooling\"}},\"getAccountLiquidity(address)\":{\"details\":\"The interface of this function is intentionally kept compatible with Compound and Venus Core\",\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"error\":\"Always NO_ERROR for compatibility with Venus core tooling\",\"liquidity\":\"Account liquidity in excess of liquidation threshold requirements,\",\"shortfall\":\"Account shortfall below liquidation threshold requirements\"}},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market.\",\"returns\":{\"_0\":\"markets The list of market addresses\"}},\"getAssetsIn(address)\":{\"params\":{\"account\":\"The address of the account to pull assets for\"},\"returns\":{\"_0\":\"A list with the assets the account has entered\"}},\"getBorrowingPower(address)\":{\"details\":\"The interface of this function is intentionally kept compatible with Compound and Venus Core\",\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"error\":\"Always NO_ERROR for compatibility with Venus core tooling\",\"liquidity\":\"Account liquidity in excess of collateral requirements,\",\"shortfall\":\"Account shortfall below collateral requirements\"}},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"details\":\"The interface of this function is intentionally kept compatible with Compound and Venus Core\",\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\",\"vTokenModify\":\"The market to hypothetically redeem/borrow in\"},\"returns\":{\"error\":\"Always NO_ERROR for compatibility with Venus core tooling\",\"liquidity\":\"Hypothetical account liquidity in excess of collateral requirements,\",\"shortfall\":\"Hypothetical account shortfall below collateral requirements\"}},\"getRewardDistributors()\":{\"returns\":{\"_0\":\"Array of RewardDistributor addresses\"}},\"getRewardsByMarket(address)\":{\"params\":{\"vToken\":\"The vToken to get the reward speeds for\"},\"returns\":{\"rewardSpeeds\":\"Array of total supply and borrow speeds and reward token for all reward distributors\"}},\"healAccount(address)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"CollateralExceedsThreshold error is thrown when the collateral is too big for healingSnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset\",\"params\":{\"user\":\"account to heal\"}},\"initialize(uint256,address)\":{\"params\":{\"accessControlManager\":\"Access control manager contract address\",\"loopLimit\":\"Limit for the loops can iterate to avoid the DOS\"}},\"isComptroller()\":{\"returns\":{\"_0\":\"Always true\"}},\"isMarketListed(address)\":{\"params\":{\"vToken\":\"vToken Address for the market to check\"},\"returns\":{\"_0\":\"listed True if listed otherwise false\"}},\"liquidateAccount(address,(address,address,uint256)[])\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidationInsufficientCollateral error is thrown when there is not enough collateral to cover the debtSnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset\",\"params\":{\"borrower\":\"the borrower address\",\"orders\":\"an array of liquidation orders\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"custom:error\":\"PriceError if the oracle returns an invalid price\",\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"vTokenBorrowed\":\"The address of the borrowed vToken\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"error\":\"Always NO_ERROR for compatibility with Venus core tooling\",\"tokensToSeize\":\"Number of vTokenCollateral tokens to be seized in a liquidation\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"preLiquidateHook(address,address,address,uint256,bool)\":{\"custom:error\":\"ActionPaused error is thrown if liquidations are paused in this marketMarketNotListed error is thrown if either collateral or borrowed token is not listedTooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factorMinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidationsInsufficientShortfall is thrown when trying to liquidate a healthy accountSnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset\",\"params\":{\"borrower\":\"The address of the borrower\",\"repayAmount\":\"The amount of underlying being repaid\",\"skipLiquidityCheck\":\"Allows the borrow to be liquidated regardless of the account liquidity\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"preMintHook(address,address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ActionPaused error is thrown if supplying to this market is pausedMarketNotListed error is thrown when the market is not listedSupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\",\"params\":{\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\",\"vToken\":\"The market to verify the mint against\"}},\"preRedeemHook(address,address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ActionPaused error is thrown if withdrawals are paused in this marketMarketNotListed error is thrown when the market is not listedInsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvencySnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset\",\"params\":{\"redeemTokens\":\"The number of vTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\",\"vToken\":\"The market to verify the redeem against\"}},\"preRepayHook(address,address)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ActionPaused error is thrown if repayments are paused in this marketMarketNotListed error is thrown when the market is not listed\",\"params\":{\"borrower\":\"The account which would borrowed the asset\",\"vToken\":\"The market to verify the repay against\"}},\"preSeizeHook(address,address,address,address)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ActionPaused error is thrown if seizing this type of collateral is pausedMarketNotListed error is thrown if either collateral or borrowed token is not listedComptrollerMismatch error is when seizer contract or seized asset belong to different pools\",\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizerContract\":\"Contract that tries to seize the asset (either borrowed vToken or Comptroller)\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"preTransferHook(address,address,address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ActionPaused error is thrown if withdrawals are paused in this marketMarketNotListed error is thrown when the market is not listedInsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvencySnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset\",\"params\":{\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of vTokens to transfer\",\"vToken\":\"The market to verify the transfer against\"}},\"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\"}},\"setActionsPaused(address[],uint8[],bool)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"details\":\"This function is restricted by the AccessControlManager\",\"params\":{\"actionsList\":\"List of action ids to pause/unpause\",\"marketsList\":\"Markets to pause/unpause the actions on\",\"paused\":\"The new paused state (true=paused, false=unpaused)\"}},\"setCloseFactor(uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:event\":\"Emits NewCloseFactor on success\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"}},\"setCollateralFactor(address,uint256,uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"MarketNotListed error is thrown when the market is not listedInvalidCollateralFactor error is thrown when collateral factor is too highInvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factorPriceError is thrown when the oracle returns an invalid price for the asset\",\"custom:event\":\"Emits NewCollateralFactor when collateral factor is updated and NewLiquidationThreshold when liquidation threshold is updated\",\"details\":\"This function is restricted by the AccessControlManager\",\"params\":{\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\",\"newLiquidationThresholdMantissa\":\"The new liquidation threshold, scaled by 1e18\",\"vToken\":\"The market to set the factor on\"}},\"setForcedLiquidation(address,bool)\":{\"params\":{\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"setLiquidationIncentive(uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:event\":\"Emits NewLiquidationIncentive on success\",\"details\":\"This function is restricted by the AccessControlManager\",\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\"}},\"setMarketBorrowCaps(address[],uint256[])\":{\"custom:access\":\"Controlled by AccessControlManager\",\"details\":\"This function is restricted by the AccessControlManagerA borrow cap of type(uint256).max corresponds to unlimited borrowing.Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed until the total borrows amount goes below the new borrow cap\",\"params\":{\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\",\"vTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\"}},\"setMarketSupplyCaps(address[],uint256[])\":{\"custom:access\":\"Controlled by AccessControlManager\",\"details\":\"This function is restricted by the AccessControlManagerA supply cap of type(uint256).max corresponds to unlimited supply.Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed until the total supplies amount goes below the new supply cap\",\"params\":{\"newSupplyCaps\":\"The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\",\"vTokens\":\"The addresses of the markets (tokens) to change the supply caps for\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinLiquidatableCollateral(uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"details\":\"This function is restricted by the AccessControlManager\",\"params\":{\"newMinLiquidatableCollateral\":\"The new min liquidatable collateral (in USD).\"}},\"setPriceOracle(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when the new oracle address is zero\",\"custom:event\":\"Emits NewPriceOracle on success\",\"details\":\"Only callable by the admin\",\"params\":{\"newOracle\":\"Address of the new price oracle to set\"}},\"supportMarket(address)\":{\"custom:access\":\"Only PoolRegistry\",\"custom:error\":\"MarketAlreadyListed is thrown if the market is already listed in this pool\",\"details\":\"Only callable by the PoolRegistry\",\"params\":{\"vToken\":\"The address of the market (token) to list\"}},\"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.\"},\"updatePrices(address)\":{\"params\":{\"account\":\"Address of the account to get associated tokens with\"}}},\"stateVariables\":{\"poolRegistry\":{\"custom:oz-upgrades-unsafe-allow\":\"state-variable-immutable\"}},\"title\":\"Comptroller\",\"version\":1},\"userdoc\":{\"errors\":{\"ActionPaused(address,uint8)\":[{\"notice\":\"Thrown when trying to perform an action that is paused\"}],\"BorrowCapExceeded(address,uint256)\":[{\"notice\":\"Thrown if the borrow cap is exceeded\"}],\"ComptrollerMismatch()\":[{\"notice\":\"Thrown when a market has an unexpected comptroller\"}],\"InsufficientLiquidity()\":[{\"notice\":\"Thrown when the account doesn't have enough liquidity to redeem or borrow\"}],\"InsufficientShortfall()\":[{\"notice\":\"Thrown when trying to liquidate a healthy account\"}],\"InvalidCollateralFactor()\":[{\"notice\":\"Thrown when collateral factor exceeds the upper bound\"}],\"InvalidLiquidationThreshold()\":[{\"notice\":\"Thrown when liquidation threshold exceeds the collateral factor\"}],\"MarketAlreadyListed(address)\":[{\"notice\":\"Thrown when trying to add a market that is already listed\"}],\"MarketNotCollateral(address,address)\":[{\"notice\":\"Thrown when user is not member of market\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the market is not listed\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"MinimalCollateralViolated(uint256,uint256)\":[{\"notice\":\"Thrown during the liquidation if user's total collateral amount is lower than a predefined threshold. In this case only batch liquidations (either liquidateAccount or healAccount) are available.\"}],\"NonzeroBorrowBalance()\":[{\"notice\":\"Thrown if the user is trying to exit a market in which they have an outstanding debt\"}],\"PriceError(address)\":[{\"notice\":\"Thrown when the oracle returns an invalid price for some asset\"}],\"SnapshotError(address,address)\":[{\"notice\":\"Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\"}],\"SupplyCapExceeded(address,uint256)\":[{\"notice\":\"Thrown if the supply cap is exceeded\"}],\"TooMuchRepay()\":[{\"notice\":\"Thrown when trying to repay more than allowed by close factor\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"UnexpectedSender(address,address)\":[{\"notice\":\"Thrown when the action is only available to specific sender, but the real sender was different\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"ActionPausedMarket(address,uint8,bool)\":{\"notice\":\"Emitted when an action is paused on a market\"},\"IsForcedLiquidationEnabledUpdated(address,bool)\":{\"notice\":\"Emitted when forced liquidation is enabled or disabled for a market\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"MarketExited(address,address)\":{\"notice\":\"Emitted when an account exits a market\"},\"MarketSupported(address)\":{\"notice\":\"Emitted when a market is supported\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"NewBorrowCap(address,uint256)\":{\"notice\":\"Emitted when borrow cap for a vToken is changed\"},\"NewCloseFactor(uint256,uint256)\":{\"notice\":\"Emitted when close factor is changed by admin\"},\"NewCollateralFactor(address,uint256,uint256)\":{\"notice\":\"Emitted when a collateral factor is changed by admin\"},\"NewLiquidationIncentive(uint256,uint256)\":{\"notice\":\"Emitted when liquidation incentive is changed by admin\"},\"NewLiquidationThreshold(address,uint256,uint256)\":{\"notice\":\"Emitted when liquidation threshold is changed by admin\"},\"NewMinLiquidatableCollateral(uint256,uint256)\":{\"notice\":\"Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\"},\"NewPriceOracle(address,address)\":{\"notice\":\"Emitted when price oracle is changed\"},\"NewRewardsDistributor(address,address)\":{\"notice\":\"Emitted when a rewards distributor is added\"},\"NewSupplyCap(address,uint256)\":{\"notice\":\"Emitted when supply cap for a vToken is changed\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\"\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"addRewardsDistributor(address)\":{\"notice\":\"Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account is entered in a given market\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation; enabling them to be used as collateral\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation; disabling them as collateral\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity with respect to liquidation threshold requirements\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the assets an account has entered\"},\"getBorrowingPower(address)\":{\"notice\":\"Determine the current account liquidity with respect to collateral requirements\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"getRewardDistributors()\":{\"notice\":\"Return all reward distributors for this pool\"},\"getRewardsByMarket(address)\":{\"notice\":\"Returns reward speed given a vToken\"},\"healAccount(address)\":{\"notice\":\"Seizes all the remaining collateral, makes msg.sender repay the existing borrows, and treats the rest of the debt as bad debt (for each market). The sender has to repay a certain percentage of the debt, computed as collateral / (borrows * liquidationIncentive).\"},\"isComptroller()\":{\"notice\":\"A marker method that returns true for a valid Comptroller contract\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Flag indicating whether forced liquidation enabled for a market\"},\"isMarketListed(address)\":{\"notice\":\"Check if a market is marked as listed (active)\"},\"liquidateAccount(address,(address,address,uint256)[])\":{\"notice\":\"Liquidates all borrows of the borrower. Callable only if the collateral is less than a predefined threshold, and the account collateral can be seized to cover all borrows. If the collateral is higher than the threshold, use regular liquidations. If the collateral is below the threshold, and the account is insolvent, use healAccount.\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"liquidationIncentiveMantissa()\":{\"notice\":\"Multiplier representing the discount on collateral that a liquidator receives\"},\"markets(address)\":{\"notice\":\"Official mapping of vTokens -> Market metadata\"},\"minLiquidatableCollateral()\":{\"notice\":\"Minimal collateral required for regular (non-batch) liquidations\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"preBorrowHook(address,address,uint256)\":{\"notice\":\"disable-eslint\"},\"preLiquidateHook(address,address,address,uint256,bool)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"preMintHook(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"preRedeemHook(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"preRepayHook(address,address)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"preSeizeHook(address,address,address,address)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"preTransferHook(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setActionsPaused(address[],uint8[],bool)\":{\"notice\":\"Pause/unpause specified actions\"},\"setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor to use when liquidating borrows\"},\"setCollateralFactor(address,uint256,uint256)\":{\"notice\":\"Sets the collateralFactor for a market\"},\"setForcedLiquidation(address,bool)\":{\"notice\":\"Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity\"},\"setLiquidationIncentive(uint256)\":{\"notice\":\"Sets liquidationIncentive\"},\"setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\"},\"setMarketSupplyCaps(address[],uint256[])\":{\"notice\":\"Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the for loop iteration limit to avoid DOS\"},\"setMinLiquidatableCollateral(uint256)\":{\"notice\":\"Set the given collateral threshold for non-batch liquidations. Regular liquidations will fail if the collateral amount is less than this threshold. Liquidators should use batch operations like liquidateAccount or healAccount.\"},\"setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the Comptroller\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\"},\"supportMarket(address)\":{\"notice\":\"Add the market to the markets mapping and set it as listed\"},\"updatePrices(address)\":{\"notice\":\"Update the prices of all the tokens associated with the provided account\"}},\"notice\":\"The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating, and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow, as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed the `minLiquidatableCollateral` for the `Comptroller`: - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool. - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic verifying that the repay amount does not exceed the close factor.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller.sol\":\"Comptroller\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"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/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.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"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/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/protocol-reserve/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/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor is changed by admin\\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow.\\n * @param vTokenAddress The address of the asset to be removed\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return NO_ERROR;\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\n _checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = accountAssets[user];\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = accountAssets[borrower];\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n _ensureMaxLoops(numMarkets);\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Enables forced liquidations for a market. If forced liquidation is enabled,\\n * borrows in the market may be liquidated regardless of the account liquidity\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall Hypothetical account shortfall below collateral requirements\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Check if a market is marked as listed (active)\\n * @param vToken vToken Address for the market to check\\n * @return listed True if listed otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].isListed;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n VToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the market specified, otherwise false.\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = accountAssets[account];\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n }\\n\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = accountAssets[account];\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x42f9cceba5f1b4d82047f930a7049740d13ab36004bb1a58b462b9e111c08665\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x44c67531518072db11bf6eafe29499073724346a7855579b09a9da049742d879\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // Multiplier representing the most one can borrow against their collateral in this market.\\n // For instance, 0.9 to allow borrowing 90% of collateral value.\\n // Must be between 0 and 1, and stored as a mantissa.\\n uint256 collateralFactorMantissa;\\n // Multiplier representing the collateralization after which the borrow is eligible\\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n // value. Must be between 0 and collateral factor, stored as a mantissa.\\n uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\n enum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n }\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint256 public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n /**\\n * @notice Official mapping of vTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\\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\":\"0xdfc033911c20e09516110ae3f94740b4be1a065baee4412a708e25a25568eac8\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x3f8ec4e18bca1fdf8619966f4f6e095e205517a78f8c741b87fe82125754f96f\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x1f17b8e3fdd89657d488250140f6d6abeb04f2b822467139687487f9c1dbe397\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"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\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each block for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller private comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlock(address[],uint32[],uint32[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumber();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\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 */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumber = getBlockNumber();\\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n function getBlockNumber() public view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumber();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplyIndex = supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowIndex = borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\\n blockNumber = supplyState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\\n\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n supplyState.index = safe224(\\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n supplyState.block = blockNumber;\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\\n blockNumber = borrowState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n borrowState.index = safe224(\\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n borrowState.block = blockNumber;\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0x598aad1a12d6a895f82a8b619000099efe53994fe89522b41adaa68819fac652\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n /**\\n * Reentrancy Guard **\\n */\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\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 /**\\n * @notice Construct a new money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\n );\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n _borrowFresh(msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == _getBlockNumber()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockDelta block difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockDelta;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return amount The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return rate The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this v\\n * @return rate The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number */\\n uint256 currentBlockNumber = _getBlockNumber();\\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentBlockNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n _reduceReservesFresh(totalReservesNew);\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is sending the assets for supply\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `_doTransferIn` for the minter and the mintAmount.\\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n }\\n\\n /**\\n * @notice User redeems vTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n */\\n function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\\n * On success, the vToken has redeemAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(redeemer, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrower User who borrows the assets\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the borrower and the borrowAmount.\\n * On success, the vToken borrowAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(borrower, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call _doTransferIn for the payer and the repayAmount\\n * On success, the vToken holds an additional repayAmount of cash.\\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == NO_ERROR, \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetInterestRateModelFreshCheck();\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n }\\n\\n /**\\n * Safe Token **\\n */\\n\\n /**\\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\\n * This function returns the actual amount received,\\n * which may be less than `amount` if there is a fee attached to the transfer.\\n * @param from Sender of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n * @return Actual amount received\\n */\\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n // Return the amount that was *actually* transferred\\n return balanceAfter - balanceBefore;\\n }\\n\\n /**\\n * @dev Just a regular ERC-20 transfer, reverts on failure\\n * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n _setComptroller(comptroller_);\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = _getBlockNumber();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying tokens owned by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n * @return Current block number\\n */\\n function _getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xf4f49f4a1718a36a7cbd413e959d957eade62d4ad96c0ebde4562e53cac72f7e\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\n\\n // Maximum borrow rate that can ever be applied (.0005% / block)\\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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[48] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves block delta is changed\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x777842977e2441dd79f4781ff61f431dda351c3d33862e40063ef58d03b489a1\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x909eb76841ebd57d8f53686b76b1a09da7bbbbcddb29510c41674d5aa84c713e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b50604051620055ea380380620055ea833981016040819052620000349162000149565b6200003f816200005d565b6001600160a01b0381166080526200005662000088565b506200017b565b6001600160a01b03811662000085576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff1615620000f55760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161462000147576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6000602082840312156200015c57600080fd5b81516001600160a01b03811681146200017457600080fd5b9392505050565b60805161544c6200019e600039600081816106f00152612ba8015261544c6000f3fe608060405234801561001057600080fd5b50600436106103775760003560e01c80638da5cb5b116101d3578063c488847b11610104578063e30c3978116100a2578063e89d51ad1161007c578063e89d51ad14610845578063eade3eed14610858578063ede4edd01461086b578063f2fde38b1461087e57600080fd5b8063e30c397814610818578063e85a296014610829578063e87554461461083c57600080fd5b8063da35a26f116100de578063da35a26f146107d6578063db5c65de146107e9578063dce15449146107f2578063df71403b1461080557600080fd5b8063c488847b14610788578063cab4f84c146107b0578063d136af44146107c357600080fd5b8063afcff50f11610171578063b4a0bdf31161014b578063b4a0bdf31461073a578063be26317e1461074b578063c0891ba914610755578063c29982381461076857600080fd5b8063afcff50f146106eb578063b0772d0b14610712578063b2068e841461071a57600080fd5b806392136395116101ad5780639213639514610671578063929fe9a114610684578063a8431081146106c5578063abfceffc146106d857600080fd5b80638da5cb5b146105fd5780638e6470ea1461060e5780638e8f294b1461062157600080fd5b806352d84d1e116102ad5780636d0be88d1161024b5780637dc0d1d0116102255780637dc0d1d0146105a157806380d45a2d146105b45780638b3113f6146105c75780638c1ac18a146105da57600080fd5b80636d0be88d1461057e578063715018a61461059157806379ba50971461059957600080fd5b80635c21b6c5116102875780635c21b6c5146105305780635cc4fdeb146105435780635ec88c791461055657806361252fd11461056957600080fd5b806352d84d1e146104df578063530e784f1461050a57806356aaee2d1461051d57600080fd5b80632bce219c1161031a5780634ada90af116102f45780634ada90af146104825780634e79238f1461048b578063520b6c74146104b9578063528a174c146104cc57600080fd5b80632bce219c146104235780633d98a1e5146104365780634a5844321461046257600080fd5b806312348e961161035657806312348e96146103d7578063186db48f146103ea5780631bc41f28146103fd57806324aaa2201461041057600080fd5b80627e3dd21461037c57806302c3bcbb146103945780630e32cb86146103c2575b600080fd5b60015b60405190151581526020015b60405180910390f35b6103b46103a2366004614997565b60d16020526000908152604090205481565b60405190815260200161038b565b6103d56103d0366004614997565b610891565b005b6103d56103e53660046149b4565b6108a5565b6103d56103f8366004614a19565b610a0b565b6103d561040b366004614a85565b610b84565b6103d561041e366004614aef565b610f53565b6103d5610431366004614b73565b611020565b61037f610444366004614997565b6001600160a01b0316600090815260cd602052604090205460ff1690565b6103b4610470366004614997565b60cf6020526000908152604090205481565b6103b460cb5481565b61049e610499366004614bfb565b611407565b6040805193845260208401929092529082015260600161038b565b6103d56104c73660046149b4565b611438565b61049e6104da366004614997565b611496565b6104f26104ed3660046149b4565b6114c1565b6040516001600160a01b03909116815260200161038b565b6103d5610518366004614997565b6114eb565b6103d561052b366004614997565b61154f565b6103d561053e366004614997565b611772565b6103d5610551366004614c41565b61189e565b61049e610564366004614997565b611adb565b610571611aed565b60405161038b9190614c76565b6103d561058c366004614cc3565b611b4f565b6103d5611cc5565b6103d5611cd9565b60c9546104f2906001600160a01b031681565b6103d56105c23660046149b4565b611d50565b6103d56105d5366004614d14565b611d61565b61037f6105e8366004614997565b60d56020526000908152604090205460ff1681565b6033546001600160a01b03166104f2565b6103d561061c366004614d4d565b611e2e565b61065461062f366004614997565b60cd6020526000908152604090208054600182015460029092015460ff909116919083565b60408051931515845260208401929092529082015260600161038b565b6103d561067f366004614997565b611f44565b61037f610692366004614d8e565b6001600160a01b03808216600090815260cd60209081526040808320938616835260039093019052205460ff1692915050565b6103d56106d33660046149b4565b61232a565b6105716106e6366004614997565b612418565b6104f27f000000000000000000000000000000000000000000000000000000000000000081565b61057161248e565b61072d610728366004614997565b6124ee565b60405161038b9190614dbc565b6097546001600160a01b03166104f2565b6103b46101075481565b6103d5610763366004614d4d565b612731565b61077b610776366004614e34565b6129c1565b60405161038b9190614ef9565b61079b610796366004614d4d565b612a78565b6040805192835260208301919091520161038b565b6103d56107be366004614997565b612ba3565b6103d56107d1366004614a19565b612dd7565b6103d56107e4366004614f31565b612f94565b6103b460d05481565b6104f2610800366004614f56565b6130b5565b6103d5610813366004614d4d565b6130ed565b6065546001600160a01b03166104f2565b61037f610837366004614f91565b61351c565b6103b460ca5481565b6103d5610853366004614fc6565b613573565b6103d5610866366004614d8e565b613777565b6103b4610879366004614997565b6139b1565b6103d561088c366004614997565b613c23565b610899613c94565b6108a281613cee565b50565b6108e36040518060400160405280601781526020017f736574436c6f7365466163746f722875696e7432353629000000000000000000815250613da5565b80670c7d713b49da000010156109575760405162461bcd60e51b815260206004820152602e60248201527f436c6f736520666163746f722067726561746572207468616e206d6178696d7560448201526d369031b637b9b2903330b1ba37b960911b60648201526084015b60405180910390fd5b8066b1a2bc2ec5000011156109c55760405162461bcd60e51b815260206004820152602e60248201527f436c6f736520666163746f7220736d616c6c6572207468616e206d696e696d7560448201526d369031b637b9b2903330b1ba37b960911b606482015260840161094e565b60ca80549082905560408051828152602081018490527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd991015b60405180910390a15050565b610a2c60405180606001604052806028815260200161532a60289139613da5565b82818115801590610a3c57508082145b610a785760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b604482015260640161094e565b610a8182613e43565b60005b82811015610b7b57848482818110610a9e57610a9e615020565b9050602002013560cf6000898985818110610abb57610abb615020565b9050602002016020810190610ad09190614997565b6001600160a01b03168152602081019190915260400160002055868682818110610afc57610afc615020565b9050602002016020810190610b119190614997565b6001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f6868684818110610b4d57610b4d615020565b90506020020135604051610b6391815260200190565b60405180910390a2610b748161504c565b9050610a84565b50505050505050565b610b8f846004613e76565b6001600160a01b038416600090815260cd60205260409020805460ff16610bd457604051635a9a1eb960e11b81526001600160a01b038616600482015260240161094e565b306001600160a01b03851603610c7c57306001600160a01b0316856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c509190615065565b6001600160a01b031614610c7757604051630c73eb0560e01b815260040160405180910390fd5b610db4565b6001600160a01b038416600090815260cd602052604090205460ff16610cc057604051635a9a1eb960e11b81526001600160a01b038516600482015260240161094e565b836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d229190615065565b6001600160a01b0316856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8d9190615065565b6001600160a01b031614610db457604051630c73eb0560e01b815260040160405180910390fd5b6001600160a01b038216600090815260038201602052604090205460ff16610df3578482604051630cdfb2db60e31b815260040161094e929190615082565b60d35460005b81811015610b7b57600060d38281548110610e1657610e16615020565b60009182526020909120015460405163051d1d4f60e11b81526001600160a01b038a8116600483015290911691508190630a3a3a9e90602401600060405180830381600087803b158015610e6957600080fd5b505af1158015610e7d573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150610eaf908b908990600401615082565b600060405180830381600087803b158015610ec957600080fd5b505af1158015610edd573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150610f0f908b908a90600401615082565b600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b505050505080610f4c9061504c565b9050610df9565b610f746040518060600160405280602a81526020016153a3602a9139613da5565b8382610f88610f83828461509c565b613e43565b60005b828110156110165760005b8281101561100557610ff5898984818110610fb357610fb3615020565b9050602002016020810190610fc89190614997565b888884818110610fda57610fda615020565b9050602002016020810190610fef91906150bb565b87613ea2565b610ffe8161504c565b9050610f96565b5061100f8161504c565b9050610f8b565b5050505050505050565b600061102e84613fb0613fe4565b905060d054816000015111156110655760d0548151604051631a451c0f60e21b81526004810192909252602482015260440161094e565b6000611085604051806020016040528060cb548152508360400151614033565b825190915081106110b6578151604051632c1f8ef160e21b815261094e918391600401918252602082015260400190565b8160a001516000036110db5760405163095bf33360e01b815260040160405180910390fd5b826110ea610f836002836150d6565b60005b818110156112e25760cd600087878481811061110b5761110b615020565b90506060020160200160208101906111239190614997565b6001600160a01b0316815260208101919091526040016000205460ff166111935785858281811061115657611156615020565b905060600201602001602081019061116e9190614997565b604051635a9a1eb960e11b81526001600160a01b03909116600482015260240161094e565b60cd60008787848181106111a9576111a9615020565b6111bf9260206060909202019081019150614997565b6001600160a01b0316815260208101919091526040016000205460ff16611208578585828181106111f2576111f2615020565b61116e9260206060909202019081019150614997565b3686868381811061121b5761121b615020565b90506060020190508060200160208101906112369190614997565b6001600160a01b0316638bbdb6db338a60408501356112586020870187614997565b60405160e086901b6001600160e01b03191681526001600160a01b0394851660048201529284166024840152604483019190915290911660648201526001608482015260a401600060405180830381600087803b1580156112b857600080fd5b505af11580156112cc573d6000803e3d6000fd5b5050505050806112db9061504c565b90506110ed565b506001600160a01b038616600090815260cc602090815260408083208054825181850281018501909352808352919290919083018282801561134d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161132f575b505083519394506000925050505b818110156113fc57600061138884838151811061137a5761137a615020565b60200260200101518b614053565b5091505080156113eb5760405162461bcd60e51b815260206004820152602860248201527f4e6f6e7a65726f20626f72726f772062616c616e6365206166746572206c69716044820152673ab4b230ba34b7b760c11b606482015260840161094e565b506113f58161504c565b905061135b565b505050505050505050565b60008060008061141c888888886140fa61412e565b608081015160a09091015160009a919950975095505050505050565b61145960405180606001604052806025815260200161535260259139613da5565b60d080549082905560408051828152602081018490527eb4f4f153ad7f1397564a8830fef092481e8cf6a2cd3ff04f96d10ba51200a591016109ff565b6000806000806114a8856140fa613fe4565b608081015160a090910151600097919650945092505050565b60ce81815481106114d157600080fd5b6000918252602090912001546001600160a01b0316905081565b6114f3613c94565b6114fc81614363565b60c980546001600160a01b038381166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22906109ff9083908590615082565b611557613c94565b6001600160a01b038116600090815260d4602052604090205460ff16156115b15760405162461bcd60e51b815260206004820152600e60248201526d616c72656164792065786973747360901b604482015260640161094e565b60d3546115c2610f838260016150f8565b60d3805460018082019092557f915c3eb987b20e1af620c1403197bf687fb7f18513b3a73fde6e78c7072c41a60180546001600160a01b0319166001600160a01b038516908117909155600090815260d460205260408120805460ff191690921790915560ce54905b818110156116cb57836001600160a01b0316632a869a4d60ce838154811061165557611655615020565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401600060405180830381600087803b1580156116a257600080fd5b505af11580156116b6573d6000803e3d6000fd5b50505050806116c49061504c565b905061162b565b50826001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172e9190615065565b6001600160a01b0316836001600160a01b03167f066a44d77db1581603d7d8ca1ca494756c0d359c7ffacd9b2c8f78dab7aceae260405160405180910390a3505050565b6001600160a01b038116600090815260cc60209081526040808320805482518185028101850190935280835291929091908301828280156117dc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116117be575b5050835160c954949550936001600160a01b0316925060009150505b8281101561189757816001600160a01b03166396e85ced85838151811061182157611821615020565b60200260200101516040518263ffffffff1660e01b815260040161185491906001600160a01b0391909116815260200190565b600060405180830381600087803b15801561186e57600080fd5b505af1158015611882573d6000803e3d6000fd5b50505050806118909061504c565b90506117f8565b5050505050565b6118bf6040518060600160405280602c8152602001615377602c9139613da5565b6001600160a01b038316600090815260cd60205260409020805460ff1661190457604051635a9a1eb960e11b81526001600160a01b038516600482015260240161094e565b670c7d713b49da000083111561192d576040516302f22cad60e61b815260040160405180910390fd5b670de0b6b3a76400008211156119555760405162f9474b60e61b815260040160405180910390fd5b828210156119755760405162f9474b60e61b815260040160405180910390fd5b82158015906119ef575060c95460405163fc57d4df60e01b81526001600160a01b0386811660048301529091169063fc57d4df90602401602060405180830381865afa1580156119c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ed9190615110565b155b15611a175760405162e52a7d60e41b81526001600160a01b038516600482015260240161094e565b6001810154838114611a755760018201849055604080516001600160a01b0387168152602081018390529081018590527f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59060600160405180910390a15b6002820154838114611ad35760028301849055604080516001600160a01b0388168152602081018390529081018590527f9e92c7d5fef69846094f3ddcadcb9402c6ba469c461368714f1cabd8ef48b5919060600160405180910390a15b505050505050565b6000806000806114a885613fb0613fe4565b606060d3805480602002602001604051908101604052809291908181526020018280548015611b4557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611b27575b5050505050905090565b611b5a846006613e76565b611b6584848361438a565b60d35460005b81811015611ad357600060d38281548110611b8857611b88615020565b60009182526020909120015460405163051d1d4f60e11b81526001600160a01b03898116600483015290911691508190630a3a3a9e90602401600060405180830381600087803b158015611bdb57600080fd5b505af1158015611bef573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150611c21908a908a90600401615082565b600060405180830381600087803b158015611c3b57600080fd5b505af1158015611c4f573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150611c81908a908990600401615082565b600060405180830381600087803b158015611c9b57600080fd5b505af1158015611caf573d6000803e3d6000fd5b505050505080611cbe9061504c565b9050611b6b565b611ccd613c94565b611cd76000614438565b565b60655433906001600160a01b03168114611d475760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161094e565b6108a281614438565b611d58613c94565b6108a281614451565b611d826040518060600160405280602281526020016153cd60229139613da5565b611d8b82614363565b6001600160a01b038216600090815260cd602052604090205460ff16611dcf57604051635a9a1eb960e11b81526001600160a01b038316600482015260240161094e565b6001600160a01b038216600081815260d56020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b611e39836001613e76565b611e4483838361438a565b60d35460005b8181101561189757600060d38281548110611e6757611e67615020565b60009182526020909120015460405163051d1d4f60e11b81526001600160a01b03888116600483015290911691508190630a3a3a9e90602401600060405180830381600087803b158015611eba57600080fd5b505af1158015611ece573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150611f009089908990600401615082565b600060405180830381600087803b158015611f1a57600080fd5b505af1158015611f2e573d6000803e3d6000fd5b505050505080611f3d9061504c565b9050611e4a565b6001600160a01b038116600090815260cc6020908152604080832080548251818502810185019093528083529192909190830182828015611fae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611f90575b5050835160c954949550933393506001600160a01b03169150600090505b838110156120e957848181518110611fe657611fe6615020565b60200260200101516001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af115801561202d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120519190615110565b50816001600160a01b03166396e85ced86838151811061207357612073615020565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b600060405180830381600087803b1580156120c057600080fd5b505af11580156120d4573d6000803e3d6000fd5b50505050806120e29061504c565b9050611fcc565b505060006120f985613fb0613fe4565b905060d054816000015111156121305760d0548151604051631a451c0f60e21b81526004810192909252602482015260440161094e565b8060a001516000036121555760405163095bf33360e01b815260040160405180910390fd5b60408051602080820183528351825282518082018452848401518152835191820190935260cb548152909160009161218d91906144ed565b9050600061219b8383614535565b90506121bf6040518060200160405280670de0b6b3a7640000815250825190511090565b156121ea5781518351604051631a451c0f60e21b81526004810192909252602482015260440161094e565b60005b868110156113fc57600088828151811061220957612209615020565b60200260200101519050600080612220838d614053565b509150915060006122318683614033565b905082156122a45760405163b2a02ff160e01b81526001600160a01b038b811660048301528e811660248301526044820185905285169063b2a02ff190606401600060405180830381600087803b15801561228b57600080fd5b505af115801561229f573d6000803e3d6000fd5b505050505b81156123155760405163227f37ff60e11b81526001600160a01b038b811660048301528e81166024830152604482018390528516906344fe6ffe90606401600060405180830381600087803b1580156122fc57600080fd5b505af1158015612310573d6000803e3d6000fd5b505050505b50505050806123239061504c565b90506121ed565b670de0b6b3a764000081101561239c5760405162461bcd60e51b815260206004820152603160248201527f6c69717569646174696f6e20696e63656e746976652073686f756c64206265206044820152700cee4cac2e8cae440e8d0c2dc4062ca627607b1b606482015260840161094e565b6123da6040518060400160405280602081526020017f7365744c69717569646174696f6e496e63656e746976652875696e7432353629815250613da5565b60cb80549082905560408051828152602081018490527faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec131691016109ff565b6001600160a01b038116600090815260cc6020908152604080832080548251818502810185019093528083526060949383018282801561248157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612463575b5093979650505050505050565b606060ce805480602002602001604051908101604052809291908181526020018280548015611b45576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611b27575050505050905090565b60d3546060908067ffffffffffffffff81111561250d5761250d614e1e565b60405190808252806020026020018201604052801561256b57816020015b612558604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b81526020019060019003908161252b5790505b50915060005b8181101561272a57600060d3828154811061258e5761258e615020565b60009182526020808320909101546040805163f7c618c160e01b815290516001600160a01b039092169450849263f7c618c1926004808401938290030181865afa1580156125e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126049190615065565b604080516060810182526001600160a01b0380841682529151631d31307360e21b815289831660048201529293509160208301918516906374c4c1cc90602401602060405180830381865afa158015612661573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126859190615110565b8152604051637c05a7c560e01b81526001600160a01b038981166004830152602090920191851690637c05a7c590602401602060405180830381865afa1580156126d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f79190615110565b81525085848151811061270c5761270c615020565b60200260200101819052505050806127239061504c565b9050612571565b5050919050565b61273c836000613e76565b6001600160a01b038316600090815260cd602052604090205460ff1661278057604051635a9a1eb960e11b81526001600160a01b038416600482015260240161094e565b6001600160a01b038316600090815260d1602052604090205460001981146128c1576000846001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128069190615110565b905060006040518060200160405280876001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015612853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128779190615110565b90529050600061288882848761456f565b9050838111156128bd5760405163db33be3d60e01b81526001600160a01b03881660048201526024810185905260440161094e565b5050505b60d35460005b81811015611ad357600060d382815481106128e4576128e4615020565b60009182526020909120015460405163051d1d4f60e11b81526001600160a01b03898116600483015290911691508190630a3a3a9e90602401600060405180830381600087803b15801561293757600080fd5b505af115801561294b573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd915061297d908a908a90600401615082565b600060405180830381600087803b15801561299757600080fd5b505af11580156129ab573d6000803e3d6000fd5b5050505050806129ba9061504c565b90506128c7565b805160609060008167ffffffffffffffff8111156129e1576129e1614e1e565b604051908082528060200260200182016040528015612a0a578160200160208202803683370190505b50905060005b82811015612a70576000858281518110612a2c57612a2c615020565b60200260200101519050612a408133614599565b6000838381518110612a5457612a54615020565b602090810291909101015250612a698161504c565b9050612a10565b509392505050565b6000806000612a8686614695565b90506000612a9386614695565b90506000866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ad5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af99190615110565b90506000612b136040518060200160405280600081525090565b60408051602080820183526000808352835180830185529081528351808301855260cb54815284519283019094528882529192612b4f916144ed565b9250612b776040518060200160405280888152506040518060200160405280888152506144ed565b9150612b838383614535565b9050612b8f818b614033565b60009d909c509a5050505050505050505050565b612bcc7f000000000000000000000000000000000000000000000000000000000000000061473a565b6001600160a01b038116600090815260cd602052604090205460ff1615612c115760405163d005ce4760e01b81526001600160a01b038216600482015260240161094e565b806001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c739190615129565b612cbf5760405162461bcd60e51b815260206004820152601b60248201527f436f6d7074726f6c6c65723a20496e76616c69642076546f6b656e0000000000604482015260640161094e565b6001600160a01b038116600090815260cd60205260408120805460ff19166001908117825581018290556002810191909155612cfa82614767565b60d35460005b81811015612d945760d38181548110612d1b57612d1b615020565b600091825260209091200154604051632a869a4d60e01b81526001600160a01b03868116600483015290911690632a869a4d90602401600060405180830381600087803b158015612d6b57600080fd5b505af1158015612d7f573d6000803e3d6000fd5b5050505080612d8d9061504c565b9050612d00565b506040516001600160a01b03841681527faf16ad15f9e29d5140e8e81a30a92a755aa8edff3d301053c84392b70c0d09a3906020015b60405180910390a1505050565b612df86040518060600160405280602881526020016153ef60289139613da5565b826000819003612e465760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206e756d626572206f66206d61726b65747360381b604482015260640161094e565b808214612e915760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206e756d626572206f66206d61726b65747360381b604482015260640161094e565b612e9a81613e43565b60005b81811015611ad357838382818110612eb757612eb7615020565b9050602002013560d16000888885818110612ed457612ed4615020565b9050602002016020810190612ee99190614997565b6001600160a01b03168152602081019190915260400160002055858582818110612f1557612f15615020565b9050602002016020810190612f2a9190614997565b6001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f8858584818110612f6657612f66615020565b90506020020135604051612f7c91815260200190565b60405180910390a2612f8d8161504c565b9050612e9d565b600054610100900460ff1615808015612fb45750600054600160ff909116105b80612fce5750303b158015612fce575060005460ff166001145b6130315760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161094e565b6000805460ff191660011790558015613054576000805461ff0019166101001790555b61305c614836565b61306582614865565b61306e83614451565b80156130b0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001612dca565b505050565b60cc60205281600052604060002081815481106130d157600080fd5b6000918252602090912001546001600160a01b03169150829050565b6130f8836002613e76565b6001600160a01b038316600090815260cd602052604090205460ff1661313c57604051635a9a1eb960e11b81526001600160a01b038416600482015260240161094e565b6001600160a01b03808416600090815260cd60209081526040808320938616835260039093019052205460ff16613180576131768361473a565b6131803383614599565b61318982611772565b60c95460405163fc57d4df60e01b81526001600160a01b0385811660048301529091169063fc57d4df90602401602060405180830381865afa1580156131d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f79190615110565b6000036132215760405162e52a7d60e41b81526001600160a01b038416600482015260240161094e565b6001600160a01b038316600090815260cf6020526040902054600019811461335f576000846001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015613283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132a79190615110565b90506000856001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330d9190615110565b905060008161331c86856150f8565b61332691906150f8565b90508381111561335b57604051632e649eed60e01b81526001600160a01b03881660048201526024810185905260440161094e565b5050505b600061337184866000866140fa61412e565b60a0810151909150156133975760405163bb55fd2760e01b815260040160405180910390fd5b60006040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134069190615110565b905260d35490915060005b8181101561101657600060d3828154811061342e5761342e615020565b600091825260209091200154604051632352607960e01b81526001600160a01b038b811660048301528651602483015290911691508190632352607990604401600060405180830381600087803b15801561348857600080fd5b505af115801561349c573d6000803e3d6000fd5b5050604051636a95ddef60e01b81526001600160a01b038c811660048301528b811660248301528751604483015284169250636a95ddef9150606401600060405180830381600087803b1580156134f257600080fd5b505af1158015613506573d6000803e3d6000fd5b5050505050806135159061504c565b9050613411565b6001600160a01b038216600090815260d2602052604081208183600881111561354757613547615146565b600881111561355857613558615146565b815260208101919091526040016000205460ff169392505050565b61357e856005613e76565b61358783611772565b6001600160a01b038516600090815260cd602052604090205460ff166135cb57604051635a9a1eb960e11b81526001600160a01b038616600482015260240161094e565b6001600160a01b038416600090815260cd602052604090205460ff1661360f57604051635a9a1eb960e11b81526001600160a01b038516600482015260240161094e565b6040516395dd919360e01b81526001600160a01b038481166004830152600091908716906395dd919390602401602060405180830381865afa158015613659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367d9190615110565b905081806136a357506001600160a01b038616600090815260d5602052604090205460ff165b156136cf57808311156136c95760405163e46c155960e01b815260040160405180910390fd5b50611897565b60006136dd85613fb0613fe4565b905060d0548160000151116137135760d0548151604051636e61bb0560e11b81526004810192909252602482015260440161094e565b8060a001516000036137385760405163095bf33360e01b815260040160405180910390fd5b6000613754604051806020016040528060ca5481525084614033565b9050808511156110165760405163e46c155960e01b815260040160405180910390fd5b613782826003613e76565b60c9546040516396e85ced60e01b81526001600160a01b038481166004830152909116906396e85ced90602401600060405180830381600087803b1580156137c957600080fd5b505af11580156137dd573d6000803e3d6000fd5b505050506001600160a01b038216600090815260cd602052604090205460ff1661382557604051635a9a1eb960e11b81526001600160a01b038316600482015260240161094e565b60d35460005b818110156139ab5760006040518060200160405280866001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561387e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138a29190615110565b8152509050600060d383815481106138bc576138bc615020565b600091825260209091200154604051632352607960e01b81526001600160a01b0388811660048301528451602483015290911691508190632352607990604401600060405180830381600087803b15801561391657600080fd5b505af115801561392a573d6000803e3d6000fd5b5050604051636a95ddef60e01b81526001600160a01b03898116600483015288811660248301528551604483015284169250636a95ddef9150606401600060405180830381600087803b15801561398057600080fd5b505af1158015613994573d6000803e3d6000fd5b505050505050806139a49061504c565b905061382b565b50505050565b60006139be826008613e76565b816000806139cc8333614053565b5091509150806000146139f25760405163f8a5d66d60e01b815260040160405180910390fd5b6139fd85338461438a565b6001600160a01b038316600090815260cd60209081526040808320338452600381019092529091205460ff16613a395750600095945050505050565b3360009081526003820160209081526040808320805460ff1916905560cc825280832080548251818502810185019093528083529192909190830182828015613aab57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613a8d575b5050835193945083925060009150505b82811015613b0d57876001600160a01b0316848281518110613adf57613adf615020565b60200260200101516001600160a01b031603613afd57809150613b0d565b613b068161504c565b9050613abb565b50818110613b1d57613b1d61515c565b33600090815260cc6020526040902080548190613b3c90600190615172565b81548110613b4c57613b4c615020565b9060005260206000200160009054906101000a90046001600160a01b0316818381548110613b7c57613b7c615020565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080805480613bba57613bba615189565b600082815260208120820160001990810180546001600160a01b031916905590910190915560405133916001600160a01b038b16917fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d9190a35060009998505050505050505050565b613c2b613c94565b606580546001600160a01b0383166001600160a01b03199091168117909155613c5c6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b03163314611cd75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161094e565b6001600160a01b038116613d525760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b606482015260840161094e565b609780546001600160a01b038381166001600160a01b03198316179092556040519116907f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0906109ff9083908590615082565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab90613dd890339086906004016151ec565b602060405180830381865afa158015613df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e199190615129565b905080613e3f57333083604051634a3fa29360e01b815260040161094e93929190615210565b5050565b610107548111156108a2576101075460405163792bfb1b60e11b815260048101919091526024810182905260440161094e565b613e80828261351c565b15613e3f5781816040516313b3ccb160e31b815260040161094e92919061525e565b6001600160a01b038316600090815260cd602052604090205460ff16613f1b5760405162461bcd60e51b815260206004820152602860248201527f63616e6e6f742070617573652061206d61726b65742074686174206973206e6f6044820152671d081b1a5cdd195960c21b606482015260840161094e565b6001600160a01b038316600090815260d2602052604081208291846008811115613f4757613f47615146565b6008811115613f5857613f58615146565b815260200190815260200160002060006101000a81548160ff0219169083151502179055507f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d838383604051612dca9392919061527b565b6040805160208082018352600091829052825180820184526001600160a01b0394909416825260cd90522060020154815290565b61401d6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61402c8360008060008661412e565b9392505050565b600080614040848461488c565b905061404b816148b4565b949350505050565b6040516361bfb47160e11b81526001600160a01b03828116600483015260009182918291829187169063c37f68e290602401608060405180830381865afa1580156140a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140c691906152a8565b91965094509250905080156140f257858560405163015e34d960e61b815260040161094e929190615082565b509250925092565b6040805160208082018352600091829052825180820184526001600160a01b0394909416825260cd90522060010154815290565b6141676040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b038616600090815260cc60209081526040808320805482518185028101850190935280835291929091908301828280156141d157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116141b3575b505083519394506000925050505b818110156143055760008382815181106141fb576141fb615020565b602002602001015190506000806000614214848e614053565b9250925092506000604051806020016040528061423087614695565b8152509050600061424f604051806020016040528085815250836144ed565b90506000614269614263888e63ffffffff16565b836144ed565b905061427a81878d6020015161456f565b60208c01528a5161428e908390889061456f565b8b5260408b01516142a2908490879061456f565b8b60400181815250508e6001600160a01b0316876001600160a01b0316036142ed576142d3818f8d6060015161456f565b60608c018190526142e79084908f9061456f565b60608c01525b50505050505050806142fe9061504c565b90506141df565b5060008360600151846040015161431c91906150f8565b905080846020015111156143435760208401518190036080850152600060a0850152614357565b600060808501526020840151810360a08501525b50505095945050505050565b6001600160a01b0381166108a2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b038316600090815260cd60205260409020805460ff166143cf57604051635a9a1eb960e11b81526001600160a01b038516600482015260240161094e565b6001600160a01b038316600090815260038201602052604090205460ff166143f75750505050565b61440083611772565b600061441284868560006140fa61412e565b60a0810151909150156118975760405163bb55fd2760e01b815260040160405180910390fd5b606580546001600160a01b03191690556108a2816148cc565b6101075481116144ae5760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b606482015260840161094e565b61010780549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016109ff565b6040805160208101909152600081526040518060200160405280670de0b6b3a76400006145228660000151866000015161491e565b61452c91906150d6565b90529392505050565b604080516020810190915260008152604051806020016040528061452c6145688660000151670de0b6b3a764000061491e565b855161492a565b60008061457c858561488c565b905061459061458a826148b4565b84614936565b95945050505050565b6145a4826007613e76565b6001600160a01b038216600090815260cd60205260409020805460ff166145e957604051635a9a1eb960e11b81526001600160a01b038416600482015260240161094e565b6001600160a01b038216600090815260038201602052604090205460ff161561461157505050565b6001600160a01b0380831660008181526003840160209081526040808320805460ff1916600190811790915560cc835281842080549182018155845291832090910180549488166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505050565b60c95460405163fc57d4df60e01b81526001600160a01b038381166004830152600092839291169063fc57d4df90602401602060405180830381865afa1580156146e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147079190615110565b9050806000036147345760405162e52a7d60e41b81526001600160a01b038416600482015260240161094e565b92915050565b336001600160a01b038216146108a2578033604051634e9383fb60e11b815260040161094e929190615082565b60ce5460005b818110156147e057826001600160a01b031660ce828154811061479257614792615020565b6000918252602090912001546001600160a01b0316036147d05760405163d005ce4760e01b81526001600160a01b038416600482015260240161094e565b6147d98161504c565b905061476d565b505060ce805460018101825560008290527fd36cd1c74ef8d7326d8021b776c18fb5a5724b7f7bc93c2f42e43e10ef27d12a0180546001600160a01b0319166001600160a01b03841617905554613e3f81613e43565b600054610100900460ff1661485d5760405162461bcd60e51b815260040161094e906152de565b611cd7614942565b600054610100900460ff166108995760405162461bcd60e51b815260040161094e906152de565b604080516020810190915260008152604051806020016040528061452c85600001518561491e565b805160009061473490670de0b6b3a7640000906150d6565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061402c828461509c565b600061402c82846150d6565b600061402c82846150f8565b600054610100900460ff166149695760405162461bcd60e51b815260040161094e906152de565b611cd733614438565b6001600160a01b03811681146108a257600080fd5b803561499281614972565b919050565b6000602082840312156149a957600080fd5b813561402c81614972565b6000602082840312156149c657600080fd5b5035919050565b60008083601f8401126149df57600080fd5b50813567ffffffffffffffff8111156149f757600080fd5b6020830191508360208260051b8501011115614a1257600080fd5b9250929050565b60008060008060408587031215614a2f57600080fd5b843567ffffffffffffffff80821115614a4757600080fd5b614a53888389016149cd565b90965094506020870135915080821115614a6c57600080fd5b50614a79878288016149cd565b95989497509550505050565b60008060008060808587031215614a9b57600080fd5b8435614aa681614972565b93506020850135614ab681614972565b92506040850135614ac681614972565b91506060850135614ad681614972565b939692955090935050565b80151581146108a257600080fd5b600080600080600060608688031215614b0757600080fd5b853567ffffffffffffffff80821115614b1f57600080fd5b614b2b89838a016149cd565b90975095506020880135915080821115614b4457600080fd5b50614b51888289016149cd565b9094509250506040860135614b6581614ae1565b809150509295509295909350565b600080600060408486031215614b8857600080fd5b8335614b9381614972565b9250602084013567ffffffffffffffff80821115614bb057600080fd5b818601915086601f830112614bc457600080fd5b813581811115614bd357600080fd5b876020606083028501011115614be857600080fd5b6020830194508093505050509250925092565b60008060008060808587031215614c1157600080fd5b8435614c1c81614972565b93506020850135614c2c81614972565b93969395505050506040820135916060013590565b600080600060608486031215614c5657600080fd5b8335614c6181614972565b95602085013595506040909401359392505050565b6020808252825182820181905260009190848201906040850190845b81811015614cb75783516001600160a01b031683529284019291840191600101614c92565b50909695505050505050565b60008060008060808587031215614cd957600080fd5b8435614ce481614972565b93506020850135614cf481614972565b92506040850135614d0481614972565b9396929550929360600135925050565b60008060408385031215614d2757600080fd5b8235614d3281614972565b91506020830135614d4281614ae1565b809150509250929050565b600080600060608486031215614d6257600080fd5b8335614d6d81614972565b92506020840135614d7d81614972565b929592945050506040919091013590565b60008060408385031215614da157600080fd5b8235614dac81614972565b91506020830135614d4281614972565b602080825282518282018190526000919060409081850190868401855b82811015614e1157815180516001600160a01b0316855286810151878601528501518585015260609093019290850190600101614dd9565b5091979650505050505050565b634e487b7160e01b600052604160045260246000fd5b60006020808385031215614e4757600080fd5b823567ffffffffffffffff80821115614e5f57600080fd5b818501915085601f830112614e7357600080fd5b813581811115614e8557614e85614e1e565b8060051b604051601f19603f83011681018181108582111715614eaa57614eaa614e1e565b604052918252848201925083810185019188831115614ec857600080fd5b938501935b82851015614eed57614ede85614987565b84529385019392850192614ecd565b98975050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614cb757835183529284019291840191600101614f15565b60008060408385031215614f4457600080fd5b823591506020830135614d4281614972565b60008060408385031215614f6957600080fd5b8235614f7481614972565b946020939093013593505050565b80356009811061499257600080fd5b60008060408385031215614fa457600080fd5b8235614faf81614972565b9150614fbd60208401614f82565b90509250929050565b600080600080600060a08688031215614fde57600080fd5b8535614fe981614972565b94506020860135614ff981614972565b9350604086013561500981614972565b9250606086013591506080860135614b6581614ae1565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161505e5761505e615036565b5060010190565b60006020828403121561507757600080fd5b815161402c81614972565b6001600160a01b0392831681529116602082015260400190565b60008160001904831182151516156150b6576150b6615036565b500290565b6000602082840312156150cd57600080fd5b61402c82614f82565b6000826150f357634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561510b5761510b615036565b500190565b60006020828403121561512257600080fd5b5051919050565b60006020828403121561513b57600080fd5b815161402c81614ae1565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052600160045260246000fd5b60008282101561518457615184615036565b500390565b634e487b7160e01b600052603160045260246000fd5b6000815180845260005b818110156151c5576020818501810151868301820152016151a9565b818111156151d7576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061404b9083018461519f565b6001600160a01b038481168252831660208201526060604082018190526000906145909083018461519f565b6009811061525a57634e487b7160e01b600052602160045260246000fd5b9052565b6001600160a01b03831681526040810161402c602083018461523c565b6001600160a01b038416815260608101615298602083018561523c565b8215156040830152949350505050565b600080600080608085870312156152be57600080fd5b505082516020840151604085015160609095015191969095509092509050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fe7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d297365744d696e4c6971756964617461626c65436f6c6c61746572616c2875696e7432353629736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e7432353629736574416374696f6e7350617573656428616464726573735b5d2c75696e743235365b5d2c626f6f6c29736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c297365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d29a2646970667358221220adfe6c8564c2cf12f95056d37b1100418276e5cfe298e28b7b8ce3f00eea36c164736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106103775760003560e01c80638da5cb5b116101d3578063c488847b11610104578063e30c3978116100a2578063e89d51ad1161007c578063e89d51ad14610845578063eade3eed14610858578063ede4edd01461086b578063f2fde38b1461087e57600080fd5b8063e30c397814610818578063e85a296014610829578063e87554461461083c57600080fd5b8063da35a26f116100de578063da35a26f146107d6578063db5c65de146107e9578063dce15449146107f2578063df71403b1461080557600080fd5b8063c488847b14610788578063cab4f84c146107b0578063d136af44146107c357600080fd5b8063afcff50f11610171578063b4a0bdf31161014b578063b4a0bdf31461073a578063be26317e1461074b578063c0891ba914610755578063c29982381461076857600080fd5b8063afcff50f146106eb578063b0772d0b14610712578063b2068e841461071a57600080fd5b806392136395116101ad5780639213639514610671578063929fe9a114610684578063a8431081146106c5578063abfceffc146106d857600080fd5b80638da5cb5b146105fd5780638e6470ea1461060e5780638e8f294b1461062157600080fd5b806352d84d1e116102ad5780636d0be88d1161024b5780637dc0d1d0116102255780637dc0d1d0146105a157806380d45a2d146105b45780638b3113f6146105c75780638c1ac18a146105da57600080fd5b80636d0be88d1461057e578063715018a61461059157806379ba50971461059957600080fd5b80635c21b6c5116102875780635c21b6c5146105305780635cc4fdeb146105435780635ec88c791461055657806361252fd11461056957600080fd5b806352d84d1e146104df578063530e784f1461050a57806356aaee2d1461051d57600080fd5b80632bce219c1161031a5780634ada90af116102f45780634ada90af146104825780634e79238f1461048b578063520b6c74146104b9578063528a174c146104cc57600080fd5b80632bce219c146104235780633d98a1e5146104365780634a5844321461046257600080fd5b806312348e961161035657806312348e96146103d7578063186db48f146103ea5780631bc41f28146103fd57806324aaa2201461041057600080fd5b80627e3dd21461037c57806302c3bcbb146103945780630e32cb86146103c2575b600080fd5b60015b60405190151581526020015b60405180910390f35b6103b46103a2366004614997565b60d16020526000908152604090205481565b60405190815260200161038b565b6103d56103d0366004614997565b610891565b005b6103d56103e53660046149b4565b6108a5565b6103d56103f8366004614a19565b610a0b565b6103d561040b366004614a85565b610b84565b6103d561041e366004614aef565b610f53565b6103d5610431366004614b73565b611020565b61037f610444366004614997565b6001600160a01b0316600090815260cd602052604090205460ff1690565b6103b4610470366004614997565b60cf6020526000908152604090205481565b6103b460cb5481565b61049e610499366004614bfb565b611407565b6040805193845260208401929092529082015260600161038b565b6103d56104c73660046149b4565b611438565b61049e6104da366004614997565b611496565b6104f26104ed3660046149b4565b6114c1565b6040516001600160a01b03909116815260200161038b565b6103d5610518366004614997565b6114eb565b6103d561052b366004614997565b61154f565b6103d561053e366004614997565b611772565b6103d5610551366004614c41565b61189e565b61049e610564366004614997565b611adb565b610571611aed565b60405161038b9190614c76565b6103d561058c366004614cc3565b611b4f565b6103d5611cc5565b6103d5611cd9565b60c9546104f2906001600160a01b031681565b6103d56105c23660046149b4565b611d50565b6103d56105d5366004614d14565b611d61565b61037f6105e8366004614997565b60d56020526000908152604090205460ff1681565b6033546001600160a01b03166104f2565b6103d561061c366004614d4d565b611e2e565b61065461062f366004614997565b60cd6020526000908152604090208054600182015460029092015460ff909116919083565b60408051931515845260208401929092529082015260600161038b565b6103d561067f366004614997565b611f44565b61037f610692366004614d8e565b6001600160a01b03808216600090815260cd60209081526040808320938616835260039093019052205460ff1692915050565b6103d56106d33660046149b4565b61232a565b6105716106e6366004614997565b612418565b6104f27f000000000000000000000000000000000000000000000000000000000000000081565b61057161248e565b61072d610728366004614997565b6124ee565b60405161038b9190614dbc565b6097546001600160a01b03166104f2565b6103b46101075481565b6103d5610763366004614d4d565b612731565b61077b610776366004614e34565b6129c1565b60405161038b9190614ef9565b61079b610796366004614d4d565b612a78565b6040805192835260208301919091520161038b565b6103d56107be366004614997565b612ba3565b6103d56107d1366004614a19565b612dd7565b6103d56107e4366004614f31565b612f94565b6103b460d05481565b6104f2610800366004614f56565b6130b5565b6103d5610813366004614d4d565b6130ed565b6065546001600160a01b03166104f2565b61037f610837366004614f91565b61351c565b6103b460ca5481565b6103d5610853366004614fc6565b613573565b6103d5610866366004614d8e565b613777565b6103b4610879366004614997565b6139b1565b6103d561088c366004614997565b613c23565b610899613c94565b6108a281613cee565b50565b6108e36040518060400160405280601781526020017f736574436c6f7365466163746f722875696e7432353629000000000000000000815250613da5565b80670c7d713b49da000010156109575760405162461bcd60e51b815260206004820152602e60248201527f436c6f736520666163746f722067726561746572207468616e206d6178696d7560448201526d369031b637b9b2903330b1ba37b960911b60648201526084015b60405180910390fd5b8066b1a2bc2ec5000011156109c55760405162461bcd60e51b815260206004820152602e60248201527f436c6f736520666163746f7220736d616c6c6572207468616e206d696e696d7560448201526d369031b637b9b2903330b1ba37b960911b606482015260840161094e565b60ca80549082905560408051828152602081018490527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd991015b60405180910390a15050565b610a2c60405180606001604052806028815260200161532a60289139613da5565b82818115801590610a3c57508082145b610a785760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b604482015260640161094e565b610a8182613e43565b60005b82811015610b7b57848482818110610a9e57610a9e615020565b9050602002013560cf6000898985818110610abb57610abb615020565b9050602002016020810190610ad09190614997565b6001600160a01b03168152602081019190915260400160002055868682818110610afc57610afc615020565b9050602002016020810190610b119190614997565b6001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f6868684818110610b4d57610b4d615020565b90506020020135604051610b6391815260200190565b60405180910390a2610b748161504c565b9050610a84565b50505050505050565b610b8f846004613e76565b6001600160a01b038416600090815260cd60205260409020805460ff16610bd457604051635a9a1eb960e11b81526001600160a01b038616600482015260240161094e565b306001600160a01b03851603610c7c57306001600160a01b0316856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c509190615065565b6001600160a01b031614610c7757604051630c73eb0560e01b815260040160405180910390fd5b610db4565b6001600160a01b038416600090815260cd602052604090205460ff16610cc057604051635a9a1eb960e11b81526001600160a01b038516600482015260240161094e565b836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d229190615065565b6001600160a01b0316856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8d9190615065565b6001600160a01b031614610db457604051630c73eb0560e01b815260040160405180910390fd5b6001600160a01b038216600090815260038201602052604090205460ff16610df3578482604051630cdfb2db60e31b815260040161094e929190615082565b60d35460005b81811015610b7b57600060d38281548110610e1657610e16615020565b60009182526020909120015460405163051d1d4f60e11b81526001600160a01b038a8116600483015290911691508190630a3a3a9e90602401600060405180830381600087803b158015610e6957600080fd5b505af1158015610e7d573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150610eaf908b908990600401615082565b600060405180830381600087803b158015610ec957600080fd5b505af1158015610edd573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150610f0f908b908a90600401615082565b600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b505050505080610f4c9061504c565b9050610df9565b610f746040518060600160405280602a81526020016153a3602a9139613da5565b8382610f88610f83828461509c565b613e43565b60005b828110156110165760005b8281101561100557610ff5898984818110610fb357610fb3615020565b9050602002016020810190610fc89190614997565b888884818110610fda57610fda615020565b9050602002016020810190610fef91906150bb565b87613ea2565b610ffe8161504c565b9050610f96565b5061100f8161504c565b9050610f8b565b5050505050505050565b600061102e84613fb0613fe4565b905060d054816000015111156110655760d0548151604051631a451c0f60e21b81526004810192909252602482015260440161094e565b6000611085604051806020016040528060cb548152508360400151614033565b825190915081106110b6578151604051632c1f8ef160e21b815261094e918391600401918252602082015260400190565b8160a001516000036110db5760405163095bf33360e01b815260040160405180910390fd5b826110ea610f836002836150d6565b60005b818110156112e25760cd600087878481811061110b5761110b615020565b90506060020160200160208101906111239190614997565b6001600160a01b0316815260208101919091526040016000205460ff166111935785858281811061115657611156615020565b905060600201602001602081019061116e9190614997565b604051635a9a1eb960e11b81526001600160a01b03909116600482015260240161094e565b60cd60008787848181106111a9576111a9615020565b6111bf9260206060909202019081019150614997565b6001600160a01b0316815260208101919091526040016000205460ff16611208578585828181106111f2576111f2615020565b61116e9260206060909202019081019150614997565b3686868381811061121b5761121b615020565b90506060020190508060200160208101906112369190614997565b6001600160a01b0316638bbdb6db338a60408501356112586020870187614997565b60405160e086901b6001600160e01b03191681526001600160a01b0394851660048201529284166024840152604483019190915290911660648201526001608482015260a401600060405180830381600087803b1580156112b857600080fd5b505af11580156112cc573d6000803e3d6000fd5b5050505050806112db9061504c565b90506110ed565b506001600160a01b038616600090815260cc602090815260408083208054825181850281018501909352808352919290919083018282801561134d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161132f575b505083519394506000925050505b818110156113fc57600061138884838151811061137a5761137a615020565b60200260200101518b614053565b5091505080156113eb5760405162461bcd60e51b815260206004820152602860248201527f4e6f6e7a65726f20626f72726f772062616c616e6365206166746572206c69716044820152673ab4b230ba34b7b760c11b606482015260840161094e565b506113f58161504c565b905061135b565b505050505050505050565b60008060008061141c888888886140fa61412e565b608081015160a09091015160009a919950975095505050505050565b61145960405180606001604052806025815260200161535260259139613da5565b60d080549082905560408051828152602081018490527eb4f4f153ad7f1397564a8830fef092481e8cf6a2cd3ff04f96d10ba51200a591016109ff565b6000806000806114a8856140fa613fe4565b608081015160a090910151600097919650945092505050565b60ce81815481106114d157600080fd5b6000918252602090912001546001600160a01b0316905081565b6114f3613c94565b6114fc81614363565b60c980546001600160a01b038381166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22906109ff9083908590615082565b611557613c94565b6001600160a01b038116600090815260d4602052604090205460ff16156115b15760405162461bcd60e51b815260206004820152600e60248201526d616c72656164792065786973747360901b604482015260640161094e565b60d3546115c2610f838260016150f8565b60d3805460018082019092557f915c3eb987b20e1af620c1403197bf687fb7f18513b3a73fde6e78c7072c41a60180546001600160a01b0319166001600160a01b038516908117909155600090815260d460205260408120805460ff191690921790915560ce54905b818110156116cb57836001600160a01b0316632a869a4d60ce838154811061165557611655615020565b60009182526020909120015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401600060405180830381600087803b1580156116a257600080fd5b505af11580156116b6573d6000803e3d6000fd5b50505050806116c49061504c565b905061162b565b50826001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172e9190615065565b6001600160a01b0316836001600160a01b03167f066a44d77db1581603d7d8ca1ca494756c0d359c7ffacd9b2c8f78dab7aceae260405160405180910390a3505050565b6001600160a01b038116600090815260cc60209081526040808320805482518185028101850190935280835291929091908301828280156117dc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116117be575b5050835160c954949550936001600160a01b0316925060009150505b8281101561189757816001600160a01b03166396e85ced85838151811061182157611821615020565b60200260200101516040518263ffffffff1660e01b815260040161185491906001600160a01b0391909116815260200190565b600060405180830381600087803b15801561186e57600080fd5b505af1158015611882573d6000803e3d6000fd5b50505050806118909061504c565b90506117f8565b5050505050565b6118bf6040518060600160405280602c8152602001615377602c9139613da5565b6001600160a01b038316600090815260cd60205260409020805460ff1661190457604051635a9a1eb960e11b81526001600160a01b038516600482015260240161094e565b670c7d713b49da000083111561192d576040516302f22cad60e61b815260040160405180910390fd5b670de0b6b3a76400008211156119555760405162f9474b60e61b815260040160405180910390fd5b828210156119755760405162f9474b60e61b815260040160405180910390fd5b82158015906119ef575060c95460405163fc57d4df60e01b81526001600160a01b0386811660048301529091169063fc57d4df90602401602060405180830381865afa1580156119c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ed9190615110565b155b15611a175760405162e52a7d60e41b81526001600160a01b038516600482015260240161094e565b6001810154838114611a755760018201849055604080516001600160a01b0387168152602081018390529081018590527f70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc59060600160405180910390a15b6002820154838114611ad35760028301849055604080516001600160a01b0388168152602081018390529081018590527f9e92c7d5fef69846094f3ddcadcb9402c6ba469c461368714f1cabd8ef48b5919060600160405180910390a15b505050505050565b6000806000806114a885613fb0613fe4565b606060d3805480602002602001604051908101604052809291908181526020018280548015611b4557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611b27575b5050505050905090565b611b5a846006613e76565b611b6584848361438a565b60d35460005b81811015611ad357600060d38281548110611b8857611b88615020565b60009182526020909120015460405163051d1d4f60e11b81526001600160a01b03898116600483015290911691508190630a3a3a9e90602401600060405180830381600087803b158015611bdb57600080fd5b505af1158015611bef573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150611c21908a908a90600401615082565b600060405180830381600087803b158015611c3b57600080fd5b505af1158015611c4f573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150611c81908a908990600401615082565b600060405180830381600087803b158015611c9b57600080fd5b505af1158015611caf573d6000803e3d6000fd5b505050505080611cbe9061504c565b9050611b6b565b611ccd613c94565b611cd76000614438565b565b60655433906001600160a01b03168114611d475760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161094e565b6108a281614438565b611d58613c94565b6108a281614451565b611d826040518060600160405280602281526020016153cd60229139613da5565b611d8b82614363565b6001600160a01b038216600090815260cd602052604090205460ff16611dcf57604051635a9a1eb960e11b81526001600160a01b038316600482015260240161094e565b6001600160a01b038216600081815260d56020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b611e39836001613e76565b611e4483838361438a565b60d35460005b8181101561189757600060d38281548110611e6757611e67615020565b60009182526020909120015460405163051d1d4f60e11b81526001600160a01b03888116600483015290911691508190630a3a3a9e90602401600060405180830381600087803b158015611eba57600080fd5b505af1158015611ece573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd9150611f009089908990600401615082565b600060405180830381600087803b158015611f1a57600080fd5b505af1158015611f2e573d6000803e3d6000fd5b505050505080611f3d9061504c565b9050611e4a565b6001600160a01b038116600090815260cc6020908152604080832080548251818502810185019093528083529192909190830182828015611fae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611f90575b5050835160c954949550933393506001600160a01b03169150600090505b838110156120e957848181518110611fe657611fe6615020565b60200260200101516001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af115801561202d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120519190615110565b50816001600160a01b03166396e85ced86838151811061207357612073615020565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b600060405180830381600087803b1580156120c057600080fd5b505af11580156120d4573d6000803e3d6000fd5b50505050806120e29061504c565b9050611fcc565b505060006120f985613fb0613fe4565b905060d054816000015111156121305760d0548151604051631a451c0f60e21b81526004810192909252602482015260440161094e565b8060a001516000036121555760405163095bf33360e01b815260040160405180910390fd5b60408051602080820183528351825282518082018452848401518152835191820190935260cb548152909160009161218d91906144ed565b9050600061219b8383614535565b90506121bf6040518060200160405280670de0b6b3a7640000815250825190511090565b156121ea5781518351604051631a451c0f60e21b81526004810192909252602482015260440161094e565b60005b868110156113fc57600088828151811061220957612209615020565b60200260200101519050600080612220838d614053565b509150915060006122318683614033565b905082156122a45760405163b2a02ff160e01b81526001600160a01b038b811660048301528e811660248301526044820185905285169063b2a02ff190606401600060405180830381600087803b15801561228b57600080fd5b505af115801561229f573d6000803e3d6000fd5b505050505b81156123155760405163227f37ff60e11b81526001600160a01b038b811660048301528e81166024830152604482018390528516906344fe6ffe90606401600060405180830381600087803b1580156122fc57600080fd5b505af1158015612310573d6000803e3d6000fd5b505050505b50505050806123239061504c565b90506121ed565b670de0b6b3a764000081101561239c5760405162461bcd60e51b815260206004820152603160248201527f6c69717569646174696f6e20696e63656e746976652073686f756c64206265206044820152700cee4cac2e8cae440e8d0c2dc4062ca627607b1b606482015260840161094e565b6123da6040518060400160405280602081526020017f7365744c69717569646174696f6e496e63656e746976652875696e7432353629815250613da5565b60cb80549082905560408051828152602081018490527faeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec131691016109ff565b6001600160a01b038116600090815260cc6020908152604080832080548251818502810185019093528083526060949383018282801561248157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612463575b5093979650505050505050565b606060ce805480602002602001604051908101604052809291908181526020018280548015611b45576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611b27575050505050905090565b60d3546060908067ffffffffffffffff81111561250d5761250d614e1e565b60405190808252806020026020018201604052801561256b57816020015b612558604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b81526020019060019003908161252b5790505b50915060005b8181101561272a57600060d3828154811061258e5761258e615020565b60009182526020808320909101546040805163f7c618c160e01b815290516001600160a01b039092169450849263f7c618c1926004808401938290030181865afa1580156125e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126049190615065565b604080516060810182526001600160a01b0380841682529151631d31307360e21b815289831660048201529293509160208301918516906374c4c1cc90602401602060405180830381865afa158015612661573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126859190615110565b8152604051637c05a7c560e01b81526001600160a01b038981166004830152602090920191851690637c05a7c590602401602060405180830381865afa1580156126d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f79190615110565b81525085848151811061270c5761270c615020565b60200260200101819052505050806127239061504c565b9050612571565b5050919050565b61273c836000613e76565b6001600160a01b038316600090815260cd602052604090205460ff1661278057604051635a9a1eb960e11b81526001600160a01b038416600482015260240161094e565b6001600160a01b038316600090815260d1602052604090205460001981146128c1576000846001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128069190615110565b905060006040518060200160405280876001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015612853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128779190615110565b90529050600061288882848761456f565b9050838111156128bd5760405163db33be3d60e01b81526001600160a01b03881660048201526024810185905260440161094e565b5050505b60d35460005b81811015611ad357600060d382815481106128e4576128e4615020565b60009182526020909120015460405163051d1d4f60e11b81526001600160a01b03898116600483015290911691508190630a3a3a9e90602401600060405180830381600087803b15801561293757600080fd5b505af115801561294b573d6000803e3d6000fd5b505060405163db7954fd60e01b81526001600160a01b038416925063db7954fd915061297d908a908a90600401615082565b600060405180830381600087803b15801561299757600080fd5b505af11580156129ab573d6000803e3d6000fd5b5050505050806129ba9061504c565b90506128c7565b805160609060008167ffffffffffffffff8111156129e1576129e1614e1e565b604051908082528060200260200182016040528015612a0a578160200160208202803683370190505b50905060005b82811015612a70576000858281518110612a2c57612a2c615020565b60200260200101519050612a408133614599565b6000838381518110612a5457612a54615020565b602090810291909101015250612a698161504c565b9050612a10565b509392505050565b6000806000612a8686614695565b90506000612a9386614695565b90506000866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ad5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af99190615110565b90506000612b136040518060200160405280600081525090565b60408051602080820183526000808352835180830185529081528351808301855260cb54815284519283019094528882529192612b4f916144ed565b9250612b776040518060200160405280888152506040518060200160405280888152506144ed565b9150612b838383614535565b9050612b8f818b614033565b60009d909c509a5050505050505050505050565b612bcc7f000000000000000000000000000000000000000000000000000000000000000061473a565b6001600160a01b038116600090815260cd602052604090205460ff1615612c115760405163d005ce4760e01b81526001600160a01b038216600482015260240161094e565b806001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c739190615129565b612cbf5760405162461bcd60e51b815260206004820152601b60248201527f436f6d7074726f6c6c65723a20496e76616c69642076546f6b656e0000000000604482015260640161094e565b6001600160a01b038116600090815260cd60205260408120805460ff19166001908117825581018290556002810191909155612cfa82614767565b60d35460005b81811015612d945760d38181548110612d1b57612d1b615020565b600091825260209091200154604051632a869a4d60e01b81526001600160a01b03868116600483015290911690632a869a4d90602401600060405180830381600087803b158015612d6b57600080fd5b505af1158015612d7f573d6000803e3d6000fd5b5050505080612d8d9061504c565b9050612d00565b506040516001600160a01b03841681527faf16ad15f9e29d5140e8e81a30a92a755aa8edff3d301053c84392b70c0d09a3906020015b60405180910390a1505050565b612df86040518060600160405280602881526020016153ef60289139613da5565b826000819003612e465760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206e756d626572206f66206d61726b65747360381b604482015260640161094e565b808214612e915760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206e756d626572206f66206d61726b65747360381b604482015260640161094e565b612e9a81613e43565b60005b81811015611ad357838382818110612eb757612eb7615020565b9050602002013560d16000888885818110612ed457612ed4615020565b9050602002016020810190612ee99190614997565b6001600160a01b03168152602081019190915260400160002055858582818110612f1557612f15615020565b9050602002016020810190612f2a9190614997565b6001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f8858584818110612f6657612f66615020565b90506020020135604051612f7c91815260200190565b60405180910390a2612f8d8161504c565b9050612e9d565b600054610100900460ff1615808015612fb45750600054600160ff909116105b80612fce5750303b158015612fce575060005460ff166001145b6130315760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161094e565b6000805460ff191660011790558015613054576000805461ff0019166101001790555b61305c614836565b61306582614865565b61306e83614451565b80156130b0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001612dca565b505050565b60cc60205281600052604060002081815481106130d157600080fd5b6000918252602090912001546001600160a01b03169150829050565b6130f8836002613e76565b6001600160a01b038316600090815260cd602052604090205460ff1661313c57604051635a9a1eb960e11b81526001600160a01b038416600482015260240161094e565b6001600160a01b03808416600090815260cd60209081526040808320938616835260039093019052205460ff16613180576131768361473a565b6131803383614599565b61318982611772565b60c95460405163fc57d4df60e01b81526001600160a01b0385811660048301529091169063fc57d4df90602401602060405180830381865afa1580156131d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f79190615110565b6000036132215760405162e52a7d60e41b81526001600160a01b038416600482015260240161094e565b6001600160a01b038316600090815260cf6020526040902054600019811461335f576000846001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015613283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132a79190615110565b90506000856001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330d9190615110565b905060008161331c86856150f8565b61332691906150f8565b90508381111561335b57604051632e649eed60e01b81526001600160a01b03881660048201526024810185905260440161094e565b5050505b600061337184866000866140fa61412e565b60a0810151909150156133975760405163bb55fd2760e01b815260040160405180910390fd5b60006040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134069190615110565b905260d35490915060005b8181101561101657600060d3828154811061342e5761342e615020565b600091825260209091200154604051632352607960e01b81526001600160a01b038b811660048301528651602483015290911691508190632352607990604401600060405180830381600087803b15801561348857600080fd5b505af115801561349c573d6000803e3d6000fd5b5050604051636a95ddef60e01b81526001600160a01b038c811660048301528b811660248301528751604483015284169250636a95ddef9150606401600060405180830381600087803b1580156134f257600080fd5b505af1158015613506573d6000803e3d6000fd5b5050505050806135159061504c565b9050613411565b6001600160a01b038216600090815260d2602052604081208183600881111561354757613547615146565b600881111561355857613558615146565b815260208101919091526040016000205460ff169392505050565b61357e856005613e76565b61358783611772565b6001600160a01b038516600090815260cd602052604090205460ff166135cb57604051635a9a1eb960e11b81526001600160a01b038616600482015260240161094e565b6001600160a01b038416600090815260cd602052604090205460ff1661360f57604051635a9a1eb960e11b81526001600160a01b038516600482015260240161094e565b6040516395dd919360e01b81526001600160a01b038481166004830152600091908716906395dd919390602401602060405180830381865afa158015613659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367d9190615110565b905081806136a357506001600160a01b038616600090815260d5602052604090205460ff165b156136cf57808311156136c95760405163e46c155960e01b815260040160405180910390fd5b50611897565b60006136dd85613fb0613fe4565b905060d0548160000151116137135760d0548151604051636e61bb0560e11b81526004810192909252602482015260440161094e565b8060a001516000036137385760405163095bf33360e01b815260040160405180910390fd5b6000613754604051806020016040528060ca5481525084614033565b9050808511156110165760405163e46c155960e01b815260040160405180910390fd5b613782826003613e76565b60c9546040516396e85ced60e01b81526001600160a01b038481166004830152909116906396e85ced90602401600060405180830381600087803b1580156137c957600080fd5b505af11580156137dd573d6000803e3d6000fd5b505050506001600160a01b038216600090815260cd602052604090205460ff1661382557604051635a9a1eb960e11b81526001600160a01b038316600482015260240161094e565b60d35460005b818110156139ab5760006040518060200160405280866001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561387e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138a29190615110565b8152509050600060d383815481106138bc576138bc615020565b600091825260209091200154604051632352607960e01b81526001600160a01b0388811660048301528451602483015290911691508190632352607990604401600060405180830381600087803b15801561391657600080fd5b505af115801561392a573d6000803e3d6000fd5b5050604051636a95ddef60e01b81526001600160a01b03898116600483015288811660248301528551604483015284169250636a95ddef9150606401600060405180830381600087803b15801561398057600080fd5b505af1158015613994573d6000803e3d6000fd5b505050505050806139a49061504c565b905061382b565b50505050565b60006139be826008613e76565b816000806139cc8333614053565b5091509150806000146139f25760405163f8a5d66d60e01b815260040160405180910390fd5b6139fd85338461438a565b6001600160a01b038316600090815260cd60209081526040808320338452600381019092529091205460ff16613a395750600095945050505050565b3360009081526003820160209081526040808320805460ff1916905560cc825280832080548251818502810185019093528083529192909190830182828015613aab57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613a8d575b5050835193945083925060009150505b82811015613b0d57876001600160a01b0316848281518110613adf57613adf615020565b60200260200101516001600160a01b031603613afd57809150613b0d565b613b068161504c565b9050613abb565b50818110613b1d57613b1d61515c565b33600090815260cc6020526040902080548190613b3c90600190615172565b81548110613b4c57613b4c615020565b9060005260206000200160009054906101000a90046001600160a01b0316818381548110613b7c57613b7c615020565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080805480613bba57613bba615189565b600082815260208120820160001990810180546001600160a01b031916905590910190915560405133916001600160a01b038b16917fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d9190a35060009998505050505050505050565b613c2b613c94565b606580546001600160a01b0383166001600160a01b03199091168117909155613c5c6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6033546001600160a01b03163314611cd75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161094e565b6001600160a01b038116613d525760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b606482015260840161094e565b609780546001600160a01b038381166001600160a01b03198316179092556040519116907f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0906109ff9083908590615082565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab90613dd890339086906004016151ec565b602060405180830381865afa158015613df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e199190615129565b905080613e3f57333083604051634a3fa29360e01b815260040161094e93929190615210565b5050565b610107548111156108a2576101075460405163792bfb1b60e11b815260048101919091526024810182905260440161094e565b613e80828261351c565b15613e3f5781816040516313b3ccb160e31b815260040161094e92919061525e565b6001600160a01b038316600090815260cd602052604090205460ff16613f1b5760405162461bcd60e51b815260206004820152602860248201527f63616e6e6f742070617573652061206d61726b65742074686174206973206e6f6044820152671d081b1a5cdd195960c21b606482015260840161094e565b6001600160a01b038316600090815260d2602052604081208291846008811115613f4757613f47615146565b6008811115613f5857613f58615146565b815260200190815260200160002060006101000a81548160ff0219169083151502179055507f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d838383604051612dca9392919061527b565b6040805160208082018352600091829052825180820184526001600160a01b0394909416825260cd90522060020154815290565b61401d6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b61402c8360008060008661412e565b9392505050565b600080614040848461488c565b905061404b816148b4565b949350505050565b6040516361bfb47160e11b81526001600160a01b03828116600483015260009182918291829187169063c37f68e290602401608060405180830381865afa1580156140a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140c691906152a8565b91965094509250905080156140f257858560405163015e34d960e61b815260040161094e929190615082565b509250925092565b6040805160208082018352600091829052825180820184526001600160a01b0394909416825260cd90522060010154815290565b6141676040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b038616600090815260cc60209081526040808320805482518185028101850190935280835291929091908301828280156141d157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116141b3575b505083519394506000925050505b818110156143055760008382815181106141fb576141fb615020565b602002602001015190506000806000614214848e614053565b9250925092506000604051806020016040528061423087614695565b8152509050600061424f604051806020016040528085815250836144ed565b90506000614269614263888e63ffffffff16565b836144ed565b905061427a81878d6020015161456f565b60208c01528a5161428e908390889061456f565b8b5260408b01516142a2908490879061456f565b8b60400181815250508e6001600160a01b0316876001600160a01b0316036142ed576142d3818f8d6060015161456f565b60608c018190526142e79084908f9061456f565b60608c01525b50505050505050806142fe9061504c565b90506141df565b5060008360600151846040015161431c91906150f8565b905080846020015111156143435760208401518190036080850152600060a0850152614357565b600060808501526020840151810360a08501525b50505095945050505050565b6001600160a01b0381166108a2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b038316600090815260cd60205260409020805460ff166143cf57604051635a9a1eb960e11b81526001600160a01b038516600482015260240161094e565b6001600160a01b038316600090815260038201602052604090205460ff166143f75750505050565b61440083611772565b600061441284868560006140fa61412e565b60a0810151909150156118975760405163bb55fd2760e01b815260040160405180910390fd5b606580546001600160a01b03191690556108a2816148cc565b6101075481116144ae5760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b606482015260840161094e565b61010780549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016109ff565b6040805160208101909152600081526040518060200160405280670de0b6b3a76400006145228660000151866000015161491e565b61452c91906150d6565b90529392505050565b604080516020810190915260008152604051806020016040528061452c6145688660000151670de0b6b3a764000061491e565b855161492a565b60008061457c858561488c565b905061459061458a826148b4565b84614936565b95945050505050565b6145a4826007613e76565b6001600160a01b038216600090815260cd60205260409020805460ff166145e957604051635a9a1eb960e11b81526001600160a01b038416600482015260240161094e565b6001600160a01b038216600090815260038201602052604090205460ff161561461157505050565b6001600160a01b0380831660008181526003840160209081526040808320805460ff1916600190811790915560cc835281842080549182018155845291832090910180549488166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505050565b60c95460405163fc57d4df60e01b81526001600160a01b038381166004830152600092839291169063fc57d4df90602401602060405180830381865afa1580156146e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147079190615110565b9050806000036147345760405162e52a7d60e41b81526001600160a01b038416600482015260240161094e565b92915050565b336001600160a01b038216146108a2578033604051634e9383fb60e11b815260040161094e929190615082565b60ce5460005b818110156147e057826001600160a01b031660ce828154811061479257614792615020565b6000918252602090912001546001600160a01b0316036147d05760405163d005ce4760e01b81526001600160a01b038416600482015260240161094e565b6147d98161504c565b905061476d565b505060ce805460018101825560008290527fd36cd1c74ef8d7326d8021b776c18fb5a5724b7f7bc93c2f42e43e10ef27d12a0180546001600160a01b0319166001600160a01b03841617905554613e3f81613e43565b600054610100900460ff1661485d5760405162461bcd60e51b815260040161094e906152de565b611cd7614942565b600054610100900460ff166108995760405162461bcd60e51b815260040161094e906152de565b604080516020810190915260008152604051806020016040528061452c85600001518561491e565b805160009061473490670de0b6b3a7640000906150d6565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600061402c828461509c565b600061402c82846150d6565b600061402c82846150f8565b600054610100900460ff166149695760405162461bcd60e51b815260040161094e906152de565b611cd733614438565b6001600160a01b03811681146108a257600080fd5b803561499281614972565b919050565b6000602082840312156149a957600080fd5b813561402c81614972565b6000602082840312156149c657600080fd5b5035919050565b60008083601f8401126149df57600080fd5b50813567ffffffffffffffff8111156149f757600080fd5b6020830191508360208260051b8501011115614a1257600080fd5b9250929050565b60008060008060408587031215614a2f57600080fd5b843567ffffffffffffffff80821115614a4757600080fd5b614a53888389016149cd565b90965094506020870135915080821115614a6c57600080fd5b50614a79878288016149cd565b95989497509550505050565b60008060008060808587031215614a9b57600080fd5b8435614aa681614972565b93506020850135614ab681614972565b92506040850135614ac681614972565b91506060850135614ad681614972565b939692955090935050565b80151581146108a257600080fd5b600080600080600060608688031215614b0757600080fd5b853567ffffffffffffffff80821115614b1f57600080fd5b614b2b89838a016149cd565b90975095506020880135915080821115614b4457600080fd5b50614b51888289016149cd565b9094509250506040860135614b6581614ae1565b809150509295509295909350565b600080600060408486031215614b8857600080fd5b8335614b9381614972565b9250602084013567ffffffffffffffff80821115614bb057600080fd5b818601915086601f830112614bc457600080fd5b813581811115614bd357600080fd5b876020606083028501011115614be857600080fd5b6020830194508093505050509250925092565b60008060008060808587031215614c1157600080fd5b8435614c1c81614972565b93506020850135614c2c81614972565b93969395505050506040820135916060013590565b600080600060608486031215614c5657600080fd5b8335614c6181614972565b95602085013595506040909401359392505050565b6020808252825182820181905260009190848201906040850190845b81811015614cb75783516001600160a01b031683529284019291840191600101614c92565b50909695505050505050565b60008060008060808587031215614cd957600080fd5b8435614ce481614972565b93506020850135614cf481614972565b92506040850135614d0481614972565b9396929550929360600135925050565b60008060408385031215614d2757600080fd5b8235614d3281614972565b91506020830135614d4281614ae1565b809150509250929050565b600080600060608486031215614d6257600080fd5b8335614d6d81614972565b92506020840135614d7d81614972565b929592945050506040919091013590565b60008060408385031215614da157600080fd5b8235614dac81614972565b91506020830135614d4281614972565b602080825282518282018190526000919060409081850190868401855b82811015614e1157815180516001600160a01b0316855286810151878601528501518585015260609093019290850190600101614dd9565b5091979650505050505050565b634e487b7160e01b600052604160045260246000fd5b60006020808385031215614e4757600080fd5b823567ffffffffffffffff80821115614e5f57600080fd5b818501915085601f830112614e7357600080fd5b813581811115614e8557614e85614e1e565b8060051b604051601f19603f83011681018181108582111715614eaa57614eaa614e1e565b604052918252848201925083810185019188831115614ec857600080fd5b938501935b82851015614eed57614ede85614987565b84529385019392850192614ecd565b98975050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614cb757835183529284019291840191600101614f15565b60008060408385031215614f4457600080fd5b823591506020830135614d4281614972565b60008060408385031215614f6957600080fd5b8235614f7481614972565b946020939093013593505050565b80356009811061499257600080fd5b60008060408385031215614fa457600080fd5b8235614faf81614972565b9150614fbd60208401614f82565b90509250929050565b600080600080600060a08688031215614fde57600080fd5b8535614fe981614972565b94506020860135614ff981614972565b9350604086013561500981614972565b9250606086013591506080860135614b6581614ae1565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161505e5761505e615036565b5060010190565b60006020828403121561507757600080fd5b815161402c81614972565b6001600160a01b0392831681529116602082015260400190565b60008160001904831182151516156150b6576150b6615036565b500290565b6000602082840312156150cd57600080fd5b61402c82614f82565b6000826150f357634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561510b5761510b615036565b500190565b60006020828403121561512257600080fd5b5051919050565b60006020828403121561513b57600080fd5b815161402c81614ae1565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052600160045260246000fd5b60008282101561518457615184615036565b500390565b634e487b7160e01b600052603160045260246000fd5b6000815180845260005b818110156151c5576020818501810151868301820152016151a9565b818111156151d7576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061404b9083018461519f565b6001600160a01b038481168252831660208201526060604082018190526000906145909083018461519f565b6009811061525a57634e487b7160e01b600052602160045260246000fd5b9052565b6001600160a01b03831681526040810161402c602083018461523c565b6001600160a01b038416815260608101615298602083018561523c565b8215156040830152949350505050565b600080600080608085870312156152be57600080fd5b505082516020840151604085015160609095015191969095509092509050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b60608201526080019056fe7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d297365744d696e4c6971756964617461626c65436f6c6c61746572616c2875696e7432353629736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e7432353629736574416374696f6e7350617573656428616464726573735b5d2c75696e743235365b5d2c626f6f6c29736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c297365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d29a2646970667358221220adfe6c8564c2cf12f95056d37b1100418276e5cfe298e28b7b8ce3f00eea36c164736f6c634300080d0033", + "devdoc": { + "author": "Venus", + "kind": "dev", + "methods": { + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "actionPaused(address,uint8)": { + "params": { + "action": "Action to check", + "market": "vToken address" + }, + "returns": { + "_0": "paused True if the action is paused otherwise false" + } + }, + "addRewardsDistributor(address)": { + "custom:access": "Only Governance", + "custom:event": "Emits NewRewardsDistributor with distributor address", + "details": "Only callable by the admin", + "params": { + "_rewardsDistributor": "Address of the RewardDistributor contract to add" + } + }, + "checkMembership(address,address)": { + "params": { + "account": "The address of the account to check", + "vToken": "The vToken to check" + }, + "returns": { + "_0": "True if the account is in the market specified, otherwise false." + } + }, + "constructor": { + "custom:error": "ZeroAddressNotAllowed is thrown when pool registry address is zero", + "custom:oz-upgrades-unsafe-allow": "constructor", + "params": { + "poolRegistry_": "Pool registry address" + } + }, + "enterMarkets(address[])": { + "custom:access": "Not restricted", + "custom:error": "ActionPaused error is thrown if entering any of the markets is pausedMarketNotListed error is thrown if any of the markets is not listed", + "custom:event": "MarketEntered is emitted for each market on success", + "params": { + "vTokens": "The list of addresses of the vToken markets to be enabled" + }, + "returns": { + "_0": "errors An array of NO_ERROR for compatibility with Venus core tooling" + } + }, + "exitMarket(address)": { + "custom:access": "Not restricted", + "custom:error": "ActionPaused error is thrown if exiting the market is pausedNonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this marketMarketNotListed error is thrown when the market is not listedInsufficientLiquidity error is thrown if exiting the market would lead to user's insolvencySnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset", + "custom:event": "MarketExited is emitted on success", + "details": "Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow.", + "params": { + "vTokenAddress": "The address of the asset to be removed" + }, + "returns": { + "_0": "error Always NO_ERROR for compatibility with Venus core tooling" + } + }, + "getAccountLiquidity(address)": { + "details": "The interface of this function is intentionally kept compatible with Compound and Venus Core", + "params": { + "account": "The account get liquidity for" + }, + "returns": { + "error": "Always NO_ERROR for compatibility with Venus core tooling", + "liquidity": "Account liquidity in excess of liquidation threshold requirements,", + "shortfall": "Account shortfall below liquidation threshold requirements" + } + }, + "getAllMarkets()": { + "details": "The automatic getter may be used to access an individual market.", + "returns": { + "_0": "markets The list of market addresses" + } + }, + "getAssetsIn(address)": { + "params": { + "account": "The address of the account to pull assets for" + }, + "returns": { + "_0": "A list with the assets the account has entered" + } + }, + "getBorrowingPower(address)": { + "details": "The interface of this function is intentionally kept compatible with Compound and Venus Core", + "params": { + "account": "The account get liquidity for" + }, + "returns": { + "error": "Always NO_ERROR for compatibility with Venus core tooling", + "liquidity": "Account liquidity in excess of collateral requirements,", + "shortfall": "Account shortfall below collateral requirements" + } + }, + "getHypotheticalAccountLiquidity(address,address,uint256,uint256)": { + "details": "The interface of this function is intentionally kept compatible with Compound and Venus Core", + "params": { + "account": "The account to determine liquidity for", + "borrowAmount": "The amount of underlying to hypothetically borrow", + "redeemTokens": "The number of tokens to hypothetically redeem", + "vTokenModify": "The market to hypothetically redeem/borrow in" + }, + "returns": { + "error": "Always NO_ERROR for compatibility with Venus core tooling", + "liquidity": "Hypothetical account liquidity in excess of collateral requirements,", + "shortfall": "Hypothetical account shortfall below collateral requirements" + } + }, + "getRewardDistributors()": { + "returns": { + "_0": "Array of RewardDistributor addresses" + } + }, + "getRewardsByMarket(address)": { + "params": { + "vToken": "The vToken to get the reward speeds for" + }, + "returns": { + "rewardSpeeds": "Array of total supply and borrow speeds and reward token for all reward distributors" + } + }, + "healAccount(address)": { + "custom:access": "Not restricted", + "custom:error": "CollateralExceedsThreshold error is thrown when the collateral is too big for healingSnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset", + "params": { + "user": "account to heal" + } + }, + "initialize(uint256,address)": { + "params": { + "accessControlManager": "Access control manager contract address", + "loopLimit": "Limit for the loops can iterate to avoid the DOS" + } + }, + "isComptroller()": { + "returns": { + "_0": "Always true" + } + }, + "isMarketListed(address)": { + "params": { + "vToken": "vToken Address for the market to check" + }, + "returns": { + "_0": "listed True if listed otherwise false" + } + }, + "liquidateAccount(address,(address,address,uint256)[])": { + "custom:access": "Not restricted", + "custom:error": "CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidationInsufficientCollateral error is thrown when there is not enough collateral to cover the debtSnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset", + "params": { + "borrower": "the borrower address", + "orders": "an array of liquidation orders" + } + }, + "liquidateCalculateSeizeTokens(address,address,uint256)": { + "custom:error": "PriceError if the oracle returns an invalid price", + "details": "Used in liquidation (called in vToken.liquidateBorrowFresh)", + "params": { + "actualRepayAmount": "The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens", + "vTokenBorrowed": "The address of the borrowed vToken", + "vTokenCollateral": "The address of the collateral vToken" + }, + "returns": { + "error": "Always NO_ERROR for compatibility with Venus core tooling", + "tokensToSeize": "Number of vTokenCollateral tokens to be seized in a liquidation" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pendingOwner()": { + "details": "Returns the address of the pending owner." + }, + "preLiquidateHook(address,address,address,uint256,bool)": { + "custom:error": "ActionPaused error is thrown if liquidations are paused in this marketMarketNotListed error is thrown if either collateral or borrowed token is not listedTooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factorMinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidationsInsufficientShortfall is thrown when trying to liquidate a healthy accountSnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset", + "params": { + "borrower": "The address of the borrower", + "repayAmount": "The amount of underlying being repaid", + "skipLiquidityCheck": "Allows the borrow to be liquidated regardless of the account liquidity", + "vTokenBorrowed": "Asset which was borrowed by the borrower", + "vTokenCollateral": "Asset which was used as collateral and will be seized" + } + }, + "preMintHook(address,address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "ActionPaused error is thrown if supplying to this market is pausedMarketNotListed error is thrown when the market is not listedSupplyCapExceeded error is thrown if the total supply exceeds the cap after minting", + "params": { + "mintAmount": "The amount of underlying being supplied to the market in exchange for tokens", + "minter": "The account which would get the minted tokens", + "vToken": "The market to verify the mint against" + } + }, + "preRedeemHook(address,address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "ActionPaused error is thrown if withdrawals are paused in this marketMarketNotListed error is thrown when the market is not listedInsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvencySnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset", + "params": { + "redeemTokens": "The number of vTokens to exchange for the underlying asset in the market", + "redeemer": "The account which would redeem the tokens", + "vToken": "The market to verify the redeem against" + } + }, + "preRepayHook(address,address)": { + "custom:access": "Not restricted", + "custom:error": "ActionPaused error is thrown if repayments are paused in this marketMarketNotListed error is thrown when the market is not listed", + "params": { + "borrower": "The account which would borrowed the asset", + "vToken": "The market to verify the repay against" + } + }, + "preSeizeHook(address,address,address,address)": { + "custom:access": "Not restricted", + "custom:error": "ActionPaused error is thrown if seizing this type of collateral is pausedMarketNotListed error is thrown if either collateral or borrowed token is not listedComptrollerMismatch error is when seizer contract or seized asset belong to different pools", + "params": { + "borrower": "The address of the borrower", + "liquidator": "The address repaying the borrow and seizing the collateral", + "seizerContract": "Contract that tries to seize the asset (either borrowed vToken or Comptroller)", + "vTokenCollateral": "Asset which was used as collateral and will be seized" + } + }, + "preTransferHook(address,address,address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "ActionPaused error is thrown if withdrawals are paused in this marketMarketNotListed error is thrown when the market is not listedInsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvencySnapshotError is thrown if some vToken fails to return the account's supply and borrowsPriceError is thrown if the oracle returns an incorrect price for some asset", + "params": { + "dst": "The account which receives the tokens", + "src": "The account which sources the tokens", + "transferTokens": "The number of vTokens to transfer", + "vToken": "The market to verify the transfer against" + } + }, + "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" + } + }, + "setActionsPaused(address[],uint8[],bool)": { + "custom:access": "Controlled by AccessControlManager", + "details": "This function is restricted by the AccessControlManager", + "params": { + "actionsList": "List of action ids to pause/unpause", + "marketsList": "Markets to pause/unpause the actions on", + "paused": "The new paused state (true=paused, false=unpaused)" + } + }, + "setCloseFactor(uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:event": "Emits NewCloseFactor on success", + "params": { + "newCloseFactorMantissa": "New close factor, scaled by 1e18" + } + }, + "setCollateralFactor(address,uint256,uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "MarketNotListed error is thrown when the market is not listedInvalidCollateralFactor error is thrown when collateral factor is too highInvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factorPriceError is thrown when the oracle returns an invalid price for the asset", + "custom:event": "Emits NewCollateralFactor when collateral factor is updated and NewLiquidationThreshold when liquidation threshold is updated", + "details": "This function is restricted by the AccessControlManager", + "params": { + "newCollateralFactorMantissa": "The new collateral factor, scaled by 1e18", + "newLiquidationThresholdMantissa": "The new liquidation threshold, scaled by 1e18", + "vToken": "The market to set the factor on" + } + }, + "setForcedLiquidation(address,bool)": { + "params": { + "enable": "Whether to enable forced liquidations", + "vTokenBorrowed": "Borrowed vToken" + } + }, + "setLiquidationIncentive(uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:event": "Emits NewLiquidationIncentive on success", + "details": "This function is restricted by the AccessControlManager", + "params": { + "newLiquidationIncentiveMantissa": "New liquidationIncentive scaled by 1e18" + } + }, + "setMarketBorrowCaps(address[],uint256[])": { + "custom:access": "Controlled by AccessControlManager", + "details": "This function is restricted by the AccessControlManagerA borrow cap of type(uint256).max corresponds to unlimited borrowing.Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed until the total borrows amount goes below the new borrow cap", + "params": { + "newBorrowCaps": "The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.", + "vTokens": "The addresses of the markets (tokens) to change the borrow caps for" + } + }, + "setMarketSupplyCaps(address[],uint256[])": { + "custom:access": "Controlled by AccessControlManager", + "details": "This function is restricted by the AccessControlManagerA supply cap of type(uint256).max corresponds to unlimited supply.Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed until the total supplies amount goes below the new supply cap", + "params": { + "newSupplyCaps": "The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.", + "vTokens": "The addresses of the markets (tokens) to change the supply caps for" + } + }, + "setMaxLoopsLimit(uint256)": { + "params": { + "limit": "Limit for the max loops can execute at a time" + } + }, + "setMinLiquidatableCollateral(uint256)": { + "custom:access": "Controlled by AccessControlManager", + "details": "This function is restricted by the AccessControlManager", + "params": { + "newMinLiquidatableCollateral": "The new min liquidatable collateral (in USD)." + } + }, + "setPriceOracle(address)": { + "custom:error": "ZeroAddressNotAllowed is thrown when the new oracle address is zero", + "custom:event": "Emits NewPriceOracle on success", + "details": "Only callable by the admin", + "params": { + "newOracle": "Address of the new price oracle to set" + } + }, + "supportMarket(address)": { + "custom:access": "Only PoolRegistry", + "custom:error": "MarketAlreadyListed is thrown if the market is already listed in this pool", + "details": "Only callable by the PoolRegistry", + "params": { + "vToken": "The address of the market (token) to list" + } + }, + "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." + }, + "updatePrices(address)": { + "params": { + "account": "Address of the account to get associated tokens with" + } + } + }, + "stateVariables": { + "poolRegistry": { + "custom:oz-upgrades-unsafe-allow": "state-variable-immutable" + } + }, + "title": "Comptroller", + "version": 1 + }, + "userdoc": { + "errors": { + "ActionPaused(address,uint8)": [ + { + "notice": "Thrown when trying to perform an action that is paused" + } + ], + "BorrowCapExceeded(address,uint256)": [ + { + "notice": "Thrown if the borrow cap is exceeded" + } + ], + "ComptrollerMismatch()": [ + { + "notice": "Thrown when a market has an unexpected comptroller" + } + ], + "InsufficientLiquidity()": [ + { + "notice": "Thrown when the account doesn't have enough liquidity to redeem or borrow" + } + ], + "InsufficientShortfall()": [ + { + "notice": "Thrown when trying to liquidate a healthy account" + } + ], + "InvalidCollateralFactor()": [ + { + "notice": "Thrown when collateral factor exceeds the upper bound" + } + ], + "InvalidLiquidationThreshold()": [ + { + "notice": "Thrown when liquidation threshold exceeds the collateral factor" + } + ], + "MarketAlreadyListed(address)": [ + { + "notice": "Thrown when trying to add a market that is already listed" + } + ], + "MarketNotCollateral(address,address)": [ + { + "notice": "Thrown when user is not member of market" + } + ], + "MarketNotListed(address)": [ + { + "notice": "Thrown when the market is not listed" + } + ], + "MaxLoopsLimitExceeded(uint256,uint256)": [ + { + "notice": "Thrown an error on maxLoopsLimit exceeds for any loop" + } + ], + "MinimalCollateralViolated(uint256,uint256)": [ + { + "notice": "Thrown during the liquidation if user's total collateral amount is lower than a predefined threshold. In this case only batch liquidations (either liquidateAccount or healAccount) are available." + } + ], + "NonzeroBorrowBalance()": [ + { + "notice": "Thrown if the user is trying to exit a market in which they have an outstanding debt" + } + ], + "PriceError(address)": [ + { + "notice": "Thrown when the oracle returns an invalid price for some asset" + } + ], + "SnapshotError(address,address)": [ + { + "notice": "Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot" + } + ], + "SupplyCapExceeded(address,uint256)": [ + { + "notice": "Thrown if the supply cap is exceeded" + } + ], + "TooMuchRepay()": [ + { + "notice": "Thrown when trying to repay more than allowed by close factor" + } + ], + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ], + "UnexpectedSender(address,address)": [ + { + "notice": "Thrown when the action is only available to specific sender, but the real sender was different" + } + ], + "ZeroAddressNotAllowed()": [ + { + "notice": "Thrown if the supplied address is a zero address where it is not allowed" + } + ] + }, + "events": { + "ActionPausedMarket(address,uint8,bool)": { + "notice": "Emitted when an action is paused on a market" + }, + "IsForcedLiquidationEnabledUpdated(address,bool)": { + "notice": "Emitted when forced liquidation is enabled or disabled for a market" + }, + "MarketEntered(address,address)": { + "notice": "Emitted when an account enters a market" + }, + "MarketExited(address,address)": { + "notice": "Emitted when an account exits a market" + }, + "MarketSupported(address)": { + "notice": "Emitted when a market is supported" + }, + "MaxLoopsLimitUpdated(uint256,uint256)": { + "notice": "Emitted when max loops limit is set" + }, + "NewAccessControlManager(address,address)": { + "notice": "Emitted when access control manager contract address is changed" + }, + "NewBorrowCap(address,uint256)": { + "notice": "Emitted when borrow cap for a vToken is changed" + }, + "NewCloseFactor(uint256,uint256)": { + "notice": "Emitted when close factor is changed by admin" + }, + "NewCollateralFactor(address,uint256,uint256)": { + "notice": "Emitted when a collateral factor is changed by admin" + }, + "NewLiquidationIncentive(uint256,uint256)": { + "notice": "Emitted when liquidation incentive is changed by admin" + }, + "NewLiquidationThreshold(address,uint256,uint256)": { + "notice": "Emitted when liquidation threshold is changed by admin" + }, + "NewMinLiquidatableCollateral(uint256,uint256)": { + "notice": "Emitted when the collateral threshold (in USD) for non-batch liquidations is changed" + }, + "NewPriceOracle(address,address)": { + "notice": "Emitted when price oracle is changed" + }, + "NewRewardsDistributor(address,address)": { + "notice": "Emitted when a rewards distributor is added" + }, + "NewSupplyCap(address,uint256)": { + "notice": "Emitted when supply cap for a vToken is changed" + } + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "Returns the address of the access control manager contract" + }, + "accountAssets(address,uint256)": { + "notice": "Per-account mapping of \"assets you are in\"" + }, + "actionPaused(address,uint8)": { + "notice": "Checks if a certain action is paused on a market" + }, + "addRewardsDistributor(address)": { + "notice": "Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor contracts with the same rewardToken, and there could be overlaping among them considering the last reward block" + }, + "allMarkets(uint256)": { + "notice": "A list of all markets" + }, + "borrowCaps(address)": { + "notice": "Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing." + }, + "checkMembership(address,address)": { + "notice": "Returns whether the given account is entered in a given market" + }, + "closeFactorMantissa()": { + "notice": "Multiplier used to calculate the maximum repayAmount when liquidating a borrow" + }, + "enterMarkets(address[])": { + "notice": "Add assets to be included in account liquidity calculation; enabling them to be used as collateral" + }, + "exitMarket(address)": { + "notice": "Removes asset from sender's account liquidity calculation; disabling them as collateral" + }, + "getAccountLiquidity(address)": { + "notice": "Determine the current account liquidity with respect to liquidation threshold requirements" + }, + "getAllMarkets()": { + "notice": "Return all of the markets" + }, + "getAssetsIn(address)": { + "notice": "Returns the assets an account has entered" + }, + "getBorrowingPower(address)": { + "notice": "Determine the current account liquidity with respect to collateral requirements" + }, + "getHypotheticalAccountLiquidity(address,address,uint256,uint256)": { + "notice": "Determine what the account liquidity would be if the given amounts were redeemed/borrowed" + }, + "getRewardDistributors()": { + "notice": "Return all reward distributors for this pool" + }, + "getRewardsByMarket(address)": { + "notice": "Returns reward speed given a vToken" + }, + "healAccount(address)": { + "notice": "Seizes all the remaining collateral, makes msg.sender repay the existing borrows, and treats the rest of the debt as bad debt (for each market). The sender has to repay a certain percentage of the debt, computed as collateral / (borrows * liquidationIncentive)." + }, + "isComptroller()": { + "notice": "A marker method that returns true for a valid Comptroller contract" + }, + "isForcedLiquidationEnabled(address)": { + "notice": "Flag indicating whether forced liquidation enabled for a market" + }, + "isMarketListed(address)": { + "notice": "Check if a market is marked as listed (active)" + }, + "liquidateAccount(address,(address,address,uint256)[])": { + "notice": "Liquidates all borrows of the borrower. Callable only if the collateral is less than a predefined threshold, and the account collateral can be seized to cover all borrows. If the collateral is higher than the threshold, use regular liquidations. If the collateral is below the threshold, and the account is insolvent, use healAccount." + }, + "liquidateCalculateSeizeTokens(address,address,uint256)": { + "notice": "Calculate number of tokens of collateral asset to seize given an underlying amount" + }, + "liquidationIncentiveMantissa()": { + "notice": "Multiplier representing the discount on collateral that a liquidator receives" + }, + "markets(address)": { + "notice": "Official mapping of vTokens -> Market metadata" + }, + "minLiquidatableCollateral()": { + "notice": "Minimal collateral required for regular (non-batch) liquidations" + }, + "oracle()": { + "notice": "Oracle which gives the price of any given asset" + }, + "preBorrowHook(address,address,uint256)": { + "notice": "disable-eslint" + }, + "preLiquidateHook(address,address,address,uint256,bool)": { + "notice": "Checks if the liquidation should be allowed to occur" + }, + "preMintHook(address,address,uint256)": { + "notice": "Checks if the account should be allowed to mint tokens in the given market" + }, + "preRedeemHook(address,address,uint256)": { + "notice": "Checks if the account should be allowed to redeem tokens in the given market" + }, + "preRepayHook(address,address)": { + "notice": "Checks if the account should be allowed to repay a borrow in the given market" + }, + "preSeizeHook(address,address,address,address)": { + "notice": "Checks if the seizing of assets should be allowed to occur" + }, + "preTransferHook(address,address,address,uint256)": { + "notice": "Checks if the account should be allowed to transfer tokens in the given market" + }, + "setAccessControlManager(address)": { + "notice": "Sets the address of AccessControlManager" + }, + "setActionsPaused(address[],uint8[],bool)": { + "notice": "Pause/unpause specified actions" + }, + "setCloseFactor(uint256)": { + "notice": "Sets the closeFactor to use when liquidating borrows" + }, + "setCollateralFactor(address,uint256,uint256)": { + "notice": "Sets the collateralFactor for a market" + }, + "setForcedLiquidation(address,bool)": { + "notice": "Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity" + }, + "setLiquidationIncentive(uint256)": { + "notice": "Sets liquidationIncentive" + }, + "setMarketBorrowCaps(address[],uint256[])": { + "notice": "Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert." + }, + "setMarketSupplyCaps(address[],uint256[])": { + "notice": "Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert." + }, + "setMaxLoopsLimit(uint256)": { + "notice": "Set the for loop iteration limit to avoid DOS" + }, + "setMinLiquidatableCollateral(uint256)": { + "notice": "Set the given collateral threshold for non-batch liquidations. Regular liquidations will fail if the collateral amount is less than this threshold. Liquidators should use batch operations like liquidateAccount or healAccount." + }, + "setPriceOracle(address)": { + "notice": "Sets a new price oracle for the Comptroller" + }, + "supplyCaps(address)": { + "notice": "Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed" + }, + "supportMarket(address)": { + "notice": "Add the market to the markets mapping and set it as listed" + }, + "updatePrices(address)": { + "notice": "Update the prices of all the tokens associated with the provided account" + } + }, + "notice": "The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating, and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow, as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed the `minLiquidatableCollateral` for the `Comptroller`: - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool. - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic verifying that the repay amount does not exceed the close factor.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 290, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 293, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1397, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 162, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 282, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 71, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "_pendingOwner", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 150, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 5019, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "_accessControlManager", + "offset": 0, + "slot": "151", + "type": "t_contract(IAccessControlManagerV8)5204" + }, + { + "astId": 5024, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 11482, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "oracle", + "offset": 0, + "slot": "201", + "type": "t_contract(ResilientOracleInterface)5263" + }, + { + "astId": 11485, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "closeFactorMantissa", + "offset": 0, + "slot": "202", + "type": "t_uint256" + }, + { + "astId": 11488, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "liquidationIncentiveMantissa", + "offset": 0, + "slot": "203", + "type": "t_uint256" + }, + { + "astId": 11495, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "accountAssets", + "offset": 0, + "slot": "204", + "type": "t_mapping(t_address,t_array(t_contract(VToken)22158)dyn_storage)" + }, + { + "astId": 11501, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "markets", + "offset": 0, + "slot": "205", + "type": "t_mapping(t_address,t_struct(Market)11468_storage)" + }, + { + "astId": 11506, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "allMarkets", + "offset": 0, + "slot": "206", + "type": "t_array(t_contract(VToken)22158)dyn_storage" + }, + { + "astId": 11511, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "borrowCaps", + "offset": 0, + "slot": "207", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 11514, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "minLiquidatableCollateral", + "offset": 0, + "slot": "208", + "type": "t_uint256" + }, + { + "astId": 11519, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "supplyCaps", + "offset": 0, + "slot": "209", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 11527, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "_actionPaused", + "offset": 0, + "slot": "210", + "type": "t_mapping(t_address,t_mapping(t_enum(Action)11478,t_bool))" + }, + { + "astId": 11531, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "rewardsDistributors", + "offset": 0, + "slot": "211", + "type": "t_array(t_contract(RewardsDistributor)16459)dyn_storage" + }, + { + "astId": 11535, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "rewardsDistributorExists", + "offset": 0, + "slot": "212", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 11540, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "isForcedLiquidationEnabled", + "offset": 0, + "slot": "213", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 11557, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "__gap", + "offset": 0, + "slot": "214", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 14017, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "maxLoopsLimit", + "offset": 0, + "slot": "263", + "type": "t_uint256" + }, + { + "astId": 14022, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "__gap", + "offset": 0, + "slot": "264", + "type": "t_array(t_uint256)49_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_contract(RewardsDistributor)16459)dyn_storage": { + "base": "t_contract(RewardsDistributor)16459", + "encoding": "dynamic_array", + "label": "contract RewardsDistributor[]", + "numberOfBytes": "32" + }, + "t_array(t_contract(VToken)22158)dyn_storage": { + "base": "t_contract(VToken)22158", + "encoding": "dynamic_array", + "label": "contract VToken[]", + "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)5204": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_contract(ResilientOracleInterface)5263": { + "encoding": "inplace", + "label": "contract ResilientOracleInterface", + "numberOfBytes": "20" + }, + "t_contract(RewardsDistributor)16459": { + "encoding": "inplace", + "label": "contract RewardsDistributor", + "numberOfBytes": "20" + }, + "t_contract(VToken)22158": { + "encoding": "inplace", + "label": "contract VToken", + "numberOfBytes": "20" + }, + "t_enum(Action)11478": { + "encoding": "inplace", + "label": "enum ComptrollerStorage.Action", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_contract(VToken)22158)dyn_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => contract VToken[])", + "numberOfBytes": "32", + "value": "t_array(t_contract(VToken)22158)dyn_storage" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_enum(Action)11478,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(enum ComptrollerStorage.Action => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_enum(Action)11478,t_bool)" + }, + "t_mapping(t_address,t_struct(Market)11468_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct ComptrollerStorage.Market)", + "numberOfBytes": "32", + "value": "t_struct(Market)11468_storage" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_enum(Action)11478,t_bool)": { + "encoding": "mapping", + "key": "t_enum(Action)11478", + "label": "mapping(enum ComptrollerStorage.Action => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_struct(Market)11468_storage": { + "encoding": "inplace", + "label": "struct ComptrollerStorage.Market", + "members": [ + { + "astId": 11459, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "isListed", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 11461, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "collateralFactorMantissa", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 11463, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "liquidationThresholdMantissa", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 11467, + "contract": "contracts/Comptroller.sol:Comptroller", + "label": "accountMembership", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_bool)" + } + ], + "numberOfBytes": "128" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} diff --git a/deployments/sepolia/Comptroller_Core.json b/deployments/sepolia/Comptroller_Core.json new file mode 100644 index 000000000..44b506e26 --- /dev/null +++ b/deployments/sepolia/Comptroller_Core.json @@ -0,0 +1,176 @@ +{ + "address": "0x7Aa39ab4BcA897F403425C9C6FDbd0f882Be0D70", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xbf8012c3af28f9f6eb7c59c84df98dee54d5bcb2c2835220c10502e9756d927c", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x7Aa39ab4BcA897F403425C9C6FDbd0f882Be0D70", + "transactionIndex": 24, + "gasUsed": "392865", + "logsBloom": "0x00000000000100000000000000000000000000000000000000800001000000000000000000000000800000000000000000000000000200000000000000008000000000000000000100000000001000000001000000200000000000000000000000000000020800000000000000000800000000000000000000000000000000400000000000000000000000000000080000000000000080000000000000000000000000000000000000002000000400000000000000800000000000000000000000000000000000000000000011040000000000000000000000800000000020000000020200000000000000000000000000000800000000000000000000000000", + "blockHash": "0x8228917083d290c066efb4e7304b4ca547ad1ca74e4c9a3ea0178f903a40fd3b", + "transactionHash": "0xbf8012c3af28f9f6eb7c59c84df98dee54d5bcb2c2835220c10502e9756d927c", + "logs": [ + { + "transactionIndex": 24, + "blockNumber": 4776620, + "transactionHash": "0xbf8012c3af28f9f6eb7c59c84df98dee54d5bcb2c2835220c10502e9756d927c", + "address": "0x7Aa39ab4BcA897F403425C9C6FDbd0f882Be0D70", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000006ce54143a88cc22500d49d744fb6535d66a8294f" + ], + "data": "0x", + "logIndex": 3019, + "blockHash": "0x8228917083d290c066efb4e7304b4ca547ad1ca74e4c9a3ea0178f903a40fd3b" + }, + { + "transactionIndex": 24, + "blockNumber": 4776620, + "transactionHash": "0xbf8012c3af28f9f6eb7c59c84df98dee54d5bcb2c2835220c10502e9756d927c", + "address": "0x7Aa39ab4BcA897F403425C9C6FDbd0f882Be0D70", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 3020, + "blockHash": "0x8228917083d290c066efb4e7304b4ca547ad1ca74e4c9a3ea0178f903a40fd3b" + }, + { + "transactionIndex": 24, + "blockNumber": 4776620, + "transactionHash": "0xbf8012c3af28f9f6eb7c59c84df98dee54d5bcb2c2835220c10502e9756d927c", + "address": "0x7Aa39ab4BcA897F403425C9C6FDbd0f882Be0D70", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 3021, + "blockHash": "0x8228917083d290c066efb4e7304b4ca547ad1ca74e4c9a3ea0178f903a40fd3b" + }, + { + "transactionIndex": 24, + "blockNumber": 4776620, + "transactionHash": "0xbf8012c3af28f9f6eb7c59c84df98dee54d5bcb2c2835220c10502e9756d927c", + "address": "0x7Aa39ab4BcA897F403425C9C6FDbd0f882Be0D70", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 3022, + "blockHash": "0x8228917083d290c066efb4e7304b4ca547ad1ca74e4c9a3ea0178f903a40fd3b" + }, + { + "transactionIndex": 24, + "blockNumber": 4776620, + "transactionHash": "0xbf8012c3af28f9f6eb7c59c84df98dee54d5bcb2c2835220c10502e9756d927c", + "address": "0x7Aa39ab4BcA897F403425C9C6FDbd0f882Be0D70", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 3023, + "blockHash": "0x8228917083d290c066efb4e7304b4ca547ad1ca74e4c9a3ea0178f903a40fd3b" + } + ], + "blockNumber": 4776620, + "cumulativeGasUsed": "29230109", + "status": 1, + "byzantium": true + }, + "args": [ + "0x6cE54143a88CC22500D49D744fb6535D66a8294F", + "0xda35a26f0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/Comptroller_Curve.json b/deployments/sepolia/Comptroller_Curve.json new file mode 100644 index 000000000..099d1cada --- /dev/null +++ b/deployments/sepolia/Comptroller_Curve.json @@ -0,0 +1,176 @@ +{ + "address": "0xD298182D3ACb43e98e32757FF09C91F203e9E67E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x83e813cbbe0e5475be9eb0a9571a56d03ad23ceb2a93e377b65b443db2e8a538", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xD298182D3ACb43e98e32757FF09C91F203e9E67E", + "transactionIndex": 10, + "gasUsed": "392865", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000200000000000000008000000000000000000100000000001000000001000000200000000000000000000000000200020800000000000000000800400000000000000000000000000000400000000000000000000000000000080000000000000080000000000000000000000000000000000000002000000400000000000000800000000000000000000000000002000000000000000011040000000000000000000000800000000020000000020200000000000000000000000000000800000000000000000000000000", + "blockHash": "0x109d03df7970e4ac7eb93013130c9b31efde464be5d335870292534dbc30373a", + "transactionHash": "0x83e813cbbe0e5475be9eb0a9571a56d03ad23ceb2a93e377b65b443db2e8a538", + "logs": [ + { + "transactionIndex": 10, + "blockNumber": 4776622, + "transactionHash": "0x83e813cbbe0e5475be9eb0a9571a56d03ad23ceb2a93e377b65b443db2e8a538", + "address": "0xD298182D3ACb43e98e32757FF09C91F203e9E67E", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000006ce54143a88cc22500d49d744fb6535d66a8294f" + ], + "data": "0x", + "logIndex": 24, + "blockHash": "0x109d03df7970e4ac7eb93013130c9b31efde464be5d335870292534dbc30373a" + }, + { + "transactionIndex": 10, + "blockNumber": 4776622, + "transactionHash": "0x83e813cbbe0e5475be9eb0a9571a56d03ad23ceb2a93e377b65b443db2e8a538", + "address": "0xD298182D3ACb43e98e32757FF09C91F203e9E67E", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 25, + "blockHash": "0x109d03df7970e4ac7eb93013130c9b31efde464be5d335870292534dbc30373a" + }, + { + "transactionIndex": 10, + "blockNumber": 4776622, + "transactionHash": "0x83e813cbbe0e5475be9eb0a9571a56d03ad23ceb2a93e377b65b443db2e8a538", + "address": "0xD298182D3ACb43e98e32757FF09C91F203e9E67E", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 26, + "blockHash": "0x109d03df7970e4ac7eb93013130c9b31efde464be5d335870292534dbc30373a" + }, + { + "transactionIndex": 10, + "blockNumber": 4776622, + "transactionHash": "0x83e813cbbe0e5475be9eb0a9571a56d03ad23ceb2a93e377b65b443db2e8a538", + "address": "0xD298182D3ACb43e98e32757FF09C91F203e9E67E", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 27, + "blockHash": "0x109d03df7970e4ac7eb93013130c9b31efde464be5d335870292534dbc30373a" + }, + { + "transactionIndex": 10, + "blockNumber": 4776622, + "transactionHash": "0x83e813cbbe0e5475be9eb0a9571a56d03ad23ceb2a93e377b65b443db2e8a538", + "address": "0xD298182D3ACb43e98e32757FF09C91F203e9E67E", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 28, + "blockHash": "0x109d03df7970e4ac7eb93013130c9b31efde464be5d335870292534dbc30373a" + } + ], + "blockNumber": 4776622, + "cumulativeGasUsed": "2085227", + "status": 1, + "byzantium": true + }, + "args": [ + "0x6cE54143a88CC22500D49D744fb6535D66a8294F", + "0xda35a26f0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/Comptroller_Stablecoins.json b/deployments/sepolia/Comptroller_Stablecoins.json new file mode 100644 index 000000000..242db8045 --- /dev/null +++ b/deployments/sepolia/Comptroller_Stablecoins.json @@ -0,0 +1,176 @@ +{ + "address": "0x18eF8D2bee415b731C25662568dc1035001cEB2c", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x4e96d6bb29e0c123f0d305b69710253e730d70a91828894221a0cde49833c223", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x18eF8D2bee415b731C25662568dc1035001cEB2c", + "transactionIndex": 57, + "gasUsed": "392865", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800800000000000000000000000000000000000000000000000000000200000000000000008000002000000000000100000000001000000001000000200000000000000000000000000000020800000000000000000800000000000008000000000000000000400000000000000000000000000000080000000000000080000000000000000000000000000000000000002000000400000000000000800000000000000000000000000000000000000000000011040000000000000000000000800000000020000000020200000000000000000000000000000800000000000000000000000000", + "blockHash": "0x96ecc77b1aaab5d45ecb80e5e6625f3ad26c7e1e7f37d390b3adb06c9876d2a6", + "transactionHash": "0x4e96d6bb29e0c123f0d305b69710253e730d70a91828894221a0cde49833c223", + "logs": [ + { + "transactionIndex": 57, + "blockNumber": 4776621, + "transactionHash": "0x4e96d6bb29e0c123f0d305b69710253e730d70a91828894221a0cde49833c223", + "address": "0x18eF8D2bee415b731C25662568dc1035001cEB2c", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000006ce54143a88cc22500d49d744fb6535d66a8294f" + ], + "data": "0x", + "logIndex": 44, + "blockHash": "0x96ecc77b1aaab5d45ecb80e5e6625f3ad26c7e1e7f37d390b3adb06c9876d2a6" + }, + { + "transactionIndex": 57, + "blockNumber": 4776621, + "transactionHash": "0x4e96d6bb29e0c123f0d305b69710253e730d70a91828894221a0cde49833c223", + "address": "0x18eF8D2bee415b731C25662568dc1035001cEB2c", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 45, + "blockHash": "0x96ecc77b1aaab5d45ecb80e5e6625f3ad26c7e1e7f37d390b3adb06c9876d2a6" + }, + { + "transactionIndex": 57, + "blockNumber": 4776621, + "transactionHash": "0x4e96d6bb29e0c123f0d305b69710253e730d70a91828894221a0cde49833c223", + "address": "0x18eF8D2bee415b731C25662568dc1035001cEB2c", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 46, + "blockHash": "0x96ecc77b1aaab5d45ecb80e5e6625f3ad26c7e1e7f37d390b3adb06c9876d2a6" + }, + { + "transactionIndex": 57, + "blockNumber": 4776621, + "transactionHash": "0x4e96d6bb29e0c123f0d305b69710253e730d70a91828894221a0cde49833c223", + "address": "0x18eF8D2bee415b731C25662568dc1035001cEB2c", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 47, + "blockHash": "0x96ecc77b1aaab5d45ecb80e5e6625f3ad26c7e1e7f37d390b3adb06c9876d2a6" + }, + { + "transactionIndex": 57, + "blockNumber": 4776621, + "transactionHash": "0x4e96d6bb29e0c123f0d305b69710253e730d70a91828894221a0cde49833c223", + "address": "0x18eF8D2bee415b731C25662568dc1035001cEB2c", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 48, + "blockHash": "0x96ecc77b1aaab5d45ecb80e5e6625f3ad26c7e1e7f37d390b3adb06c9876d2a6" + } + ], + "blockNumber": 4776621, + "cumulativeGasUsed": "10018468", + "status": 1, + "byzantium": true + }, + "args": [ + "0x6cE54143a88CC22500D49D744fb6535D66a8294F", + "0xda35a26f0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/DefaultProxyAdmin.json b/deployments/sepolia/DefaultProxyAdmin.json new file mode 100644 index 000000000..21f53423b --- /dev/null +++ b/deployments/sepolia/DefaultProxyAdmin.json @@ -0,0 +1,257 @@ +{ + "address": "0xe98a3110929c6650c73031756288Ec518f65e846", + "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": "0xa88e0a25152afedc910bbc103ba8ce70a6f1fdb3b8d1212006888b5475a5403c", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0xe98a3110929c6650c73031756288Ec518f65e846", + "transactionIndex": 0, + "gasUsed": "644163", + "logsBloom": "0x00000000000000080000000000000000000000000004000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000100000000000000000000000000000000000000000000000000004000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf6b16a12f3b79ea2732f507d29e0612db8ffe727fe715893a2522ead5eccbfa0", + "transactionHash": "0xa88e0a25152afedc910bbc103ba8ce70a6f1fdb3b8d1212006888b5475a5403c", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 4312878, + "transactionHash": "0xa88e0a25152afedc910bbc103ba8ce70a6f1fdb3b8d1212006888b5475a5403c", + "address": "0xe98a3110929c6650c73031756288Ec518f65e846", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xf6b16a12f3b79ea2732f507d29e0612db8ffe727fe715893a2522ead5eccbfa0" + } + ], + "blockNumber": 4312878, + "cumulativeGasUsed": "644163", + "status": 1, + "byzantium": true + }, + "args": ["0x94fa6078b6b8a26f0b6edffbe6501b22a10470fb"], + "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/sepolia/JumpRateModelV2_base0bps_slope450bps_jump8000bps_kink8000bps.json b/deployments/sepolia/JumpRateModelV2_base0bps_slope450bps_jump8000bps_kink8000bps.json new file mode 100644 index 000000000..71351b726 --- /dev/null +++ b/deployments/sepolia/JumpRateModelV2_base0bps_slope450bps_jump8000bps_kink8000bps.json @@ -0,0 +1,519 @@ +{ + "address": "0xe948BBE16a846988A501A33Fb6A82Af4E2f231aE", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0x36d0d0db44765fd5309a248bffe463c05cf853eaa53b36fc3a9e33c6c659e819", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xe948BBE16a846988A501A33Fb6A82Af4E2f231aE", + "transactionIndex": 68, + "gasUsed": "565128", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000", + "blockHash": "0x47ad3c459d8adb6e624465a9332a291daecd82fc87a194ce95d12e1b3e99cd06", + "transactionHash": "0x36d0d0db44765fd5309a248bffe463c05cf853eaa53b36fc3a9e33c6c659e819", + "logs": [ + { + "transactionIndex": 68, + "blockNumber": 4776630, + "transactionHash": "0x36d0d0db44765fd5309a248bffe463c05cf853eaa53b36fc3a9e33c6c659e819", + "address": "0xe948BBE16a846988A501A33Fb6A82Af4E2f231aE", + "topics": ["0x6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004a6bb770e00000000000000000000000000000000000000000000000000000052b092ef3c0000000000000000000000000000000000000000000000000b1a2bc2ec500000", + "logIndex": 76, + "blockHash": "0x47ad3c459d8adb6e624465a9332a291daecd82fc87a194ce95d12e1b3e99cd06" + } + ], + "blockNumber": 4776630, + "cumulativeGasUsed": "8192264", + "status": 1, + "byzantium": true + }, + "args": [ + 2252571, + "0", + "45000000000000000", + "800000000000000000", + "800000000000000000", + "0xbf705C00578d43B6147ab4eaE04DBBEd1ccCdc96" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"},{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":false,\"internalType\":\"uint256\",\"name\":\"baseRatePerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"kink\",\"type\":\"uint256\"}],\"name\":\"NewInterestParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"jumpMultiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"kink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"multiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"}],\"name\":\"updateJumpRateModel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"utilizationRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Arr00\",\"kind\":\"dev\",\"methods\":{\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The borrow rate percentage per block as a mantissa (scaled by 1e18)\"}},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserveFactorMantissa\":\"The current reserve factor for the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\"}},\"isInterestRateModel()\":{\"returns\":{\"_0\":\"Always true\"}},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized if the sender is not allowed to call this function\",\"params\":{\"baseRatePerYear\":\"The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\",\"jumpMultiplierPerYear\":\"The multiplierPerBlock after hitting a specified utilization point\",\"kink_\":\"The utilization point at which the jump multiplier is applied\",\"multiplierPerYear\":\"The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\"}},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market (currently unused)\"},\"returns\":{\"_0\":\"The utilization rate as a mantissa between [0, MANTISSA_ONE]\"}}},\"title\":\"Compound's JumpRateModel Contract V2 for V2 vTokens\",\"version\":1},\"userdoc\":{\"errors\":{\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}]},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"The address of the AccessControlManager contract\"},\"baseRatePerBlock()\":{\"notice\":\"The base interest rate which is the y-intercept when utilization rate is 0\"},\"blocksPerYear()\":{\"notice\":\"The approximate number of blocks per year that is assumed by the interest rate model\"},\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current borrow rate per block\"},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current supply rate per block\"},\"isInterestRateModel()\":{\"notice\":\"Indicator that this is an InterestRateModel contract (for inspection)\"},\"jumpMultiplierPerBlock()\":{\"notice\":\"The multiplier per block after hitting a specified utilization point\"},\"kink()\":{\"notice\":\"The utilization point at which the jump multiplier is applied\"},\"multiplierPerBlock()\":{\"notice\":\"The multiplier of utilization rate that gives the slope of the interest rate\"},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"notice\":\"Update the parameters of the interest rate model\"},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\"}},\"notice\":\"Supports only for V2 vTokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JumpRateModelV2.sol\":\"JumpRateModelV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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/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\"},\"contracts/BaseJumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { EXP_SCALE, MANTISSA_ONE } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Logic for Compound's JumpRateModel Contract V2.\\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\\n */\\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\\n /**\\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\\n */\\n uint256 public immutable blocksPerYear;\\n /**\\n * @notice The address of the AccessControlManager contract\\n */\\n IAccessControlManagerV8 public accessControlManager;\\n\\n /**\\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\\n */\\n uint256 public multiplierPerBlock;\\n\\n /**\\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\\n */\\n uint256 public baseRatePerBlock;\\n\\n /**\\n * @notice The multiplier per block after hitting a specified utilization point\\n */\\n uint256 public jumpMultiplierPerBlock;\\n\\n /**\\n * @notice The utilization point at which the jump multiplier is applied\\n */\\n uint256 public kink;\\n\\n event NewInterestParams(\\n uint256 baseRatePerBlock,\\n uint256 multiplierPerBlock,\\n uint256 jumpMultiplierPerBlock,\\n uint256 kink\\n );\\n\\n /**\\n * @notice Thrown when the action is prohibited by AccessControlManager\\n */\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Construct an interest rate model\\n * @param blocksPerYear_ The approximate number of blocks per year that is assumed by the interest rate model.\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @param accessControlManager_ The address of the AccessControlManager contract\\n */\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n ) {\\n require(address(accessControlManager_) != address(0), \\\"invalid ACM address\\\");\\n require(blocksPerYear_ != 0, \\\"Invalid blocks per year\\\");\\n accessControlManager = accessControlManager_;\\n blocksPerYear = blocksPerYear_;\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @custom:error Unauthorized if the sender is not allowed to call this function\\n * @custom:access Controlled by AccessControlManager\\n */\\n function updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) external virtual {\\n string memory signature = \\\"updateJumpRateModel(uint256,uint256,uint256,uint256)\\\";\\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Calculates the current supply rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param reserveFactorMantissa The current reserve factor for the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) public view virtual override returns (uint256) {\\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\\n uint256 incomeToDistribute = borrows * rateToPool;\\n uint256 supply = cash + borrows + badDebt - reserves;\\n return incomeToDistribute / supply;\\n }\\n\\n /**\\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market (currently unused)\\n * @param badDebt The amount of badDebt in the market\\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\\n */\\n function utilizationRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) public pure returns (uint256) {\\n // Utilization rate is 0 when there are no borrows and badDebt\\n if ((borrows + badDebt) == 0) {\\n return 0;\\n }\\n\\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\\n\\n if (rate > EXP_SCALE) {\\n rate = EXP_SCALE;\\n }\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Internal function to update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n */\\n function _updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) internal {\\n baseRatePerBlock = baseRatePerYear / blocksPerYear;\\n multiplierPerBlock = multiplierPerYear / blocksPerYear;\\n jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear;\\n kink = kink_;\\n\\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function _getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) internal view returns (uint256) {\\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\\n uint256 kink_ = kink;\\n\\n if (util <= kink_) {\\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n }\\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n uint256 excessUtil;\\n unchecked {\\n excessUtil = util - kink_;\\n }\\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\\n }\\n}\\n\",\"keccak256\":\"0xa2fa0aae39306f3c8ddf1c3b2fefffa15ce68406315cd95ebe2c2ac4263e7f16\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"contracts/JumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { BaseJumpRateModelV2 } from \\\"./BaseJumpRateModelV2.sol\\\";\\n\\n/**\\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\\n * @author Arr00\\n * @notice Supports only for V2 vTokens\\n */\\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n )\\n BaseJumpRateModelV2(\\n blocksPerYear_,\\n baseRatePerYear,\\n multiplierPerYear,\\n jumpMultiplierPerYear,\\n kink_,\\n accessControlManager_\\n )\\n /* solhint-disable-next-line no-empty-blocks */\\n {\\n\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view override returns (uint256) {\\n return _getBorrowRate(cash, borrows, reserves, badDebt);\\n }\\n}\\n\",\"keccak256\":\"0x4bac8ea1ed2dad59939317cc9e1a76fd55de6a745df29802f52cd97cf1c5a1ac\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b506040516109ca3803806109ca83398101604081905261002f916101a9565b8585858585856001600160a01b0381166100905760405162461bcd60e51b815260206004820152601360248201527f696e76616c69642041434d20616464726573730000000000000000000000000060448201526064015b60405180910390fd5b856000036100e05760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420626c6f636b732070657220796561720000000000000000006044820152606401610087565b600080546001600160a01b0319166001600160a01b038316179055608086905261010c8585858561011d565b50505050505050505050505061022f565b60805161012a908561020d565b60025560805161013a908461020d565b60015560805161014a908361020d565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b60008060008060008060c087890312156101c257600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b03811681146101ff57600080fd5b809150509295509295509295565b60008261022a57634e487b7160e01b600052601260045260246000fd5b500490565b60805161076b61025f6000396000818161012c0152818161046a0152818161049701526104c4015261076b6000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "devdoc": { + "author": "Arr00", + "kind": "dev", + "methods": { + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The borrow rate percentage per block as a mantissa (scaled by 1e18)" + } + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserveFactorMantissa": "The current reserve factor for the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)" + } + }, + "isInterestRateModel()": { + "returns": { + "_0": "Always true" + } + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized if the sender is not allowed to call this function", + "params": { + "baseRatePerYear": "The approximate target base APR, as a mantissa (scaled by EXP_SCALE)", + "jumpMultiplierPerYear": "The multiplierPerBlock after hitting a specified utilization point", + "kink_": "The utilization point at which the jump multiplier is applied", + "multiplierPerYear": "The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)" + } + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market (currently unused)" + }, + "returns": { + "_0": "The utilization rate as a mantissa between [0, MANTISSA_ONE]" + } + } + }, + "title": "Compound's JumpRateModel Contract V2 for V2 vTokens", + "version": 1 + }, + "userdoc": { + "errors": { + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ] + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "The address of the AccessControlManager contract" + }, + "baseRatePerBlock()": { + "notice": "The base interest rate which is the y-intercept when utilization rate is 0" + }, + "blocksPerYear()": { + "notice": "The approximate number of blocks per year that is assumed by the interest rate model" + }, + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current borrow rate per block" + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current supply rate per block" + }, + "isInterestRateModel()": { + "notice": "Indicator that this is an InterestRateModel contract (for inspection)" + }, + "jumpMultiplierPerBlock()": { + "notice": "The multiplier per block after hitting a specified utilization point" + }, + "kink()": { + "notice": "The utilization point at which the jump multiplier is applied" + }, + "multiplierPerBlock()": { + "notice": "The multiplier of utilization rate that gives the slope of the interest rate" + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "notice": "Update the parameters of the interest rate model" + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`" + } + }, + "notice": "Supports only for V2 vTokens", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7419, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "accessControlManager", + "offset": 0, + "slot": "0", + "type": "t_contract(IAccessControlManagerV8)5204" + }, + { + "astId": 7422, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "multiplierPerBlock", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 7425, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "baseRatePerBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 7428, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "jumpMultiplierPerBlock", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 7431, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "kink", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_contract(IAccessControlManagerV8)5204": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/JumpRateModelV2_base0bps_slope500bps_jump8000bps_kink7500bps.json b/deployments/sepolia/JumpRateModelV2_base0bps_slope500bps_jump8000bps_kink7500bps.json new file mode 100644 index 000000000..ce8760030 --- /dev/null +++ b/deployments/sepolia/JumpRateModelV2_base0bps_slope500bps_jump8000bps_kink7500bps.json @@ -0,0 +1,519 @@ +{ + "address": "0x1A9ca9032C7ee7335736fCaa5e8fb62b283538da", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0x41cc330f9e1282d1dc6509f7d4171eab5d8b2250195e0c67bdad61b377c0c5cf", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x1A9ca9032C7ee7335736fCaa5e8fb62b283538da", + "transactionIndex": 39, + "gasUsed": "565116", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000024000000000000000000000000080000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000", + "blockHash": "0x2e451d87e47a1a86cd3491d8a69a1685da217650cfb9d1e41475f7293c7f5724", + "transactionHash": "0x41cc330f9e1282d1dc6509f7d4171eab5d8b2250195e0c67bdad61b377c0c5cf", + "logs": [ + { + "transactionIndex": 39, + "blockNumber": 4776625, + "transactionHash": "0x41cc330f9e1282d1dc6509f7d4171eab5d8b2250195e0c67bdad61b377c0c5cf", + "address": "0x1A9ca9032C7ee7335736fCaa5e8fb62b283538da", + "topics": ["0x6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052b092ef300000000000000000000000000000000000000000000000000000052b092ef3c0000000000000000000000000000000000000000000000000a688906bd8b0000", + "logIndex": 48, + "blockHash": "0x2e451d87e47a1a86cd3491d8a69a1685da217650cfb9d1e41475f7293c7f5724" + } + ], + "blockNumber": 4776625, + "cumulativeGasUsed": "5615514", + "status": 1, + "byzantium": true + }, + "args": [ + 2252571, + "0", + "50000000000000000", + "800000000000000000", + "750000000000000000", + "0xbf705C00578d43B6147ab4eaE04DBBEd1ccCdc96" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"},{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":false,\"internalType\":\"uint256\",\"name\":\"baseRatePerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"kink\",\"type\":\"uint256\"}],\"name\":\"NewInterestParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"jumpMultiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"kink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"multiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"}],\"name\":\"updateJumpRateModel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"utilizationRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Arr00\",\"kind\":\"dev\",\"methods\":{\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The borrow rate percentage per block as a mantissa (scaled by 1e18)\"}},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserveFactorMantissa\":\"The current reserve factor for the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\"}},\"isInterestRateModel()\":{\"returns\":{\"_0\":\"Always true\"}},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized if the sender is not allowed to call this function\",\"params\":{\"baseRatePerYear\":\"The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\",\"jumpMultiplierPerYear\":\"The multiplierPerBlock after hitting a specified utilization point\",\"kink_\":\"The utilization point at which the jump multiplier is applied\",\"multiplierPerYear\":\"The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\"}},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market (currently unused)\"},\"returns\":{\"_0\":\"The utilization rate as a mantissa between [0, MANTISSA_ONE]\"}}},\"title\":\"Compound's JumpRateModel Contract V2 for V2 vTokens\",\"version\":1},\"userdoc\":{\"errors\":{\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}]},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"The address of the AccessControlManager contract\"},\"baseRatePerBlock()\":{\"notice\":\"The base interest rate which is the y-intercept when utilization rate is 0\"},\"blocksPerYear()\":{\"notice\":\"The approximate number of blocks per year that is assumed by the interest rate model\"},\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current borrow rate per block\"},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current supply rate per block\"},\"isInterestRateModel()\":{\"notice\":\"Indicator that this is an InterestRateModel contract (for inspection)\"},\"jumpMultiplierPerBlock()\":{\"notice\":\"The multiplier per block after hitting a specified utilization point\"},\"kink()\":{\"notice\":\"The utilization point at which the jump multiplier is applied\"},\"multiplierPerBlock()\":{\"notice\":\"The multiplier of utilization rate that gives the slope of the interest rate\"},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"notice\":\"Update the parameters of the interest rate model\"},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\"}},\"notice\":\"Supports only for V2 vTokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JumpRateModelV2.sol\":\"JumpRateModelV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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/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\"},\"contracts/BaseJumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { EXP_SCALE, MANTISSA_ONE } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Logic for Compound's JumpRateModel Contract V2.\\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\\n */\\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\\n /**\\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\\n */\\n uint256 public immutable blocksPerYear;\\n /**\\n * @notice The address of the AccessControlManager contract\\n */\\n IAccessControlManagerV8 public accessControlManager;\\n\\n /**\\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\\n */\\n uint256 public multiplierPerBlock;\\n\\n /**\\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\\n */\\n uint256 public baseRatePerBlock;\\n\\n /**\\n * @notice The multiplier per block after hitting a specified utilization point\\n */\\n uint256 public jumpMultiplierPerBlock;\\n\\n /**\\n * @notice The utilization point at which the jump multiplier is applied\\n */\\n uint256 public kink;\\n\\n event NewInterestParams(\\n uint256 baseRatePerBlock,\\n uint256 multiplierPerBlock,\\n uint256 jumpMultiplierPerBlock,\\n uint256 kink\\n );\\n\\n /**\\n * @notice Thrown when the action is prohibited by AccessControlManager\\n */\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Construct an interest rate model\\n * @param blocksPerYear_ The approximate number of blocks per year that is assumed by the interest rate model.\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @param accessControlManager_ The address of the AccessControlManager contract\\n */\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n ) {\\n require(address(accessControlManager_) != address(0), \\\"invalid ACM address\\\");\\n require(blocksPerYear_ != 0, \\\"Invalid blocks per year\\\");\\n accessControlManager = accessControlManager_;\\n blocksPerYear = blocksPerYear_;\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @custom:error Unauthorized if the sender is not allowed to call this function\\n * @custom:access Controlled by AccessControlManager\\n */\\n function updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) external virtual {\\n string memory signature = \\\"updateJumpRateModel(uint256,uint256,uint256,uint256)\\\";\\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Calculates the current supply rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param reserveFactorMantissa The current reserve factor for the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) public view virtual override returns (uint256) {\\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\\n uint256 incomeToDistribute = borrows * rateToPool;\\n uint256 supply = cash + borrows + badDebt - reserves;\\n return incomeToDistribute / supply;\\n }\\n\\n /**\\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market (currently unused)\\n * @param badDebt The amount of badDebt in the market\\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\\n */\\n function utilizationRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) public pure returns (uint256) {\\n // Utilization rate is 0 when there are no borrows and badDebt\\n if ((borrows + badDebt) == 0) {\\n return 0;\\n }\\n\\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\\n\\n if (rate > EXP_SCALE) {\\n rate = EXP_SCALE;\\n }\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Internal function to update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n */\\n function _updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) internal {\\n baseRatePerBlock = baseRatePerYear / blocksPerYear;\\n multiplierPerBlock = multiplierPerYear / blocksPerYear;\\n jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear;\\n kink = kink_;\\n\\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function _getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) internal view returns (uint256) {\\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\\n uint256 kink_ = kink;\\n\\n if (util <= kink_) {\\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n }\\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n uint256 excessUtil;\\n unchecked {\\n excessUtil = util - kink_;\\n }\\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\\n }\\n}\\n\",\"keccak256\":\"0xa2fa0aae39306f3c8ddf1c3b2fefffa15ce68406315cd95ebe2c2ac4263e7f16\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"contracts/JumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { BaseJumpRateModelV2 } from \\\"./BaseJumpRateModelV2.sol\\\";\\n\\n/**\\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\\n * @author Arr00\\n * @notice Supports only for V2 vTokens\\n */\\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n )\\n BaseJumpRateModelV2(\\n blocksPerYear_,\\n baseRatePerYear,\\n multiplierPerYear,\\n jumpMultiplierPerYear,\\n kink_,\\n accessControlManager_\\n )\\n /* solhint-disable-next-line no-empty-blocks */\\n {\\n\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view override returns (uint256) {\\n return _getBorrowRate(cash, borrows, reserves, badDebt);\\n }\\n}\\n\",\"keccak256\":\"0x4bac8ea1ed2dad59939317cc9e1a76fd55de6a745df29802f52cd97cf1c5a1ac\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b506040516109ca3803806109ca83398101604081905261002f916101a9565b8585858585856001600160a01b0381166100905760405162461bcd60e51b815260206004820152601360248201527f696e76616c69642041434d20616464726573730000000000000000000000000060448201526064015b60405180910390fd5b856000036100e05760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420626c6f636b732070657220796561720000000000000000006044820152606401610087565b600080546001600160a01b0319166001600160a01b038316179055608086905261010c8585858561011d565b50505050505050505050505061022f565b60805161012a908561020d565b60025560805161013a908461020d565b60015560805161014a908361020d565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b60008060008060008060c087890312156101c257600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b03811681146101ff57600080fd5b809150509295509295509295565b60008261022a57634e487b7160e01b600052601260045260246000fd5b500490565b60805161076b61025f6000396000818161012c0152818161046a0152818161049701526104c4015261076b6000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "devdoc": { + "author": "Arr00", + "kind": "dev", + "methods": { + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The borrow rate percentage per block as a mantissa (scaled by 1e18)" + } + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserveFactorMantissa": "The current reserve factor for the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)" + } + }, + "isInterestRateModel()": { + "returns": { + "_0": "Always true" + } + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized if the sender is not allowed to call this function", + "params": { + "baseRatePerYear": "The approximate target base APR, as a mantissa (scaled by EXP_SCALE)", + "jumpMultiplierPerYear": "The multiplierPerBlock after hitting a specified utilization point", + "kink_": "The utilization point at which the jump multiplier is applied", + "multiplierPerYear": "The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)" + } + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market (currently unused)" + }, + "returns": { + "_0": "The utilization rate as a mantissa between [0, MANTISSA_ONE]" + } + } + }, + "title": "Compound's JumpRateModel Contract V2 for V2 vTokens", + "version": 1 + }, + "userdoc": { + "errors": { + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ] + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "The address of the AccessControlManager contract" + }, + "baseRatePerBlock()": { + "notice": "The base interest rate which is the y-intercept when utilization rate is 0" + }, + "blocksPerYear()": { + "notice": "The approximate number of blocks per year that is assumed by the interest rate model" + }, + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current borrow rate per block" + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current supply rate per block" + }, + "isInterestRateModel()": { + "notice": "Indicator that this is an InterestRateModel contract (for inspection)" + }, + "jumpMultiplierPerBlock()": { + "notice": "The multiplier per block after hitting a specified utilization point" + }, + "kink()": { + "notice": "The utilization point at which the jump multiplier is applied" + }, + "multiplierPerBlock()": { + "notice": "The multiplier of utilization rate that gives the slope of the interest rate" + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "notice": "Update the parameters of the interest rate model" + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`" + } + }, + "notice": "Supports only for V2 vTokens", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7419, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "accessControlManager", + "offset": 0, + "slot": "0", + "type": "t_contract(IAccessControlManagerV8)5204" + }, + { + "astId": 7422, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "multiplierPerBlock", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 7425, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "baseRatePerBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 7428, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "jumpMultiplierPerBlock", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 7431, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "kink", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_contract(IAccessControlManagerV8)5204": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/JumpRateModelV2_base0bps_slope700bps_jump8000bps_kink8000bps.json b/deployments/sepolia/JumpRateModelV2_base0bps_slope700bps_jump8000bps_kink8000bps.json new file mode 100644 index 000000000..3738deaf0 --- /dev/null +++ b/deployments/sepolia/JumpRateModelV2_base0bps_slope700bps_jump8000bps_kink8000bps.json @@ -0,0 +1,519 @@ +{ + "address": "0xA03205bC635A772E533E7BE36b5701E331a70ea3", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0x4833ba8a82a49fd17b58470645de5761fa88cdb1c16afedfc383f89ff7c22faa", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xA03205bC635A772E533E7BE36b5701E331a70ea3", + "transactionIndex": 23, + "gasUsed": "565116", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000001000000000000000000000040000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf8e8eaecc89b20e16d8900c748f7c84df5228bbf91ef63f3fefc148275c0414f", + "transactionHash": "0x4833ba8a82a49fd17b58470645de5761fa88cdb1c16afedfc383f89ff7c22faa", + "logs": [ + { + "transactionIndex": 23, + "blockNumber": 4776632, + "transactionHash": "0x4833ba8a82a49fd17b58470645de5761fa88cdb1c16afedfc383f89ff7c22faa", + "address": "0xA03205bC635A772E533E7BE36b5701E331a70ea3", + "topics": ["0x6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073c400e8800000000000000000000000000000000000000000000000000000052b092ef3c0000000000000000000000000000000000000000000000000b1a2bc2ec500000", + "logIndex": 42, + "blockHash": "0xf8e8eaecc89b20e16d8900c748f7c84df5228bbf91ef63f3fefc148275c0414f" + } + ], + "blockNumber": 4776632, + "cumulativeGasUsed": "3796872", + "status": 1, + "byzantium": true + }, + "args": [ + 2252571, + "0", + "70000000000000000", + "800000000000000000", + "800000000000000000", + "0xbf705C00578d43B6147ab4eaE04DBBEd1ccCdc96" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"},{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":false,\"internalType\":\"uint256\",\"name\":\"baseRatePerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"kink\",\"type\":\"uint256\"}],\"name\":\"NewInterestParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"jumpMultiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"kink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"multiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"}],\"name\":\"updateJumpRateModel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"utilizationRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Arr00\",\"kind\":\"dev\",\"methods\":{\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The borrow rate percentage per block as a mantissa (scaled by 1e18)\"}},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserveFactorMantissa\":\"The current reserve factor for the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\"}},\"isInterestRateModel()\":{\"returns\":{\"_0\":\"Always true\"}},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized if the sender is not allowed to call this function\",\"params\":{\"baseRatePerYear\":\"The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\",\"jumpMultiplierPerYear\":\"The multiplierPerBlock after hitting a specified utilization point\",\"kink_\":\"The utilization point at which the jump multiplier is applied\",\"multiplierPerYear\":\"The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\"}},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market (currently unused)\"},\"returns\":{\"_0\":\"The utilization rate as a mantissa between [0, MANTISSA_ONE]\"}}},\"title\":\"Compound's JumpRateModel Contract V2 for V2 vTokens\",\"version\":1},\"userdoc\":{\"errors\":{\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}]},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"The address of the AccessControlManager contract\"},\"baseRatePerBlock()\":{\"notice\":\"The base interest rate which is the y-intercept when utilization rate is 0\"},\"blocksPerYear()\":{\"notice\":\"The approximate number of blocks per year that is assumed by the interest rate model\"},\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current borrow rate per block\"},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current supply rate per block\"},\"isInterestRateModel()\":{\"notice\":\"Indicator that this is an InterestRateModel contract (for inspection)\"},\"jumpMultiplierPerBlock()\":{\"notice\":\"The multiplier per block after hitting a specified utilization point\"},\"kink()\":{\"notice\":\"The utilization point at which the jump multiplier is applied\"},\"multiplierPerBlock()\":{\"notice\":\"The multiplier of utilization rate that gives the slope of the interest rate\"},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"notice\":\"Update the parameters of the interest rate model\"},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\"}},\"notice\":\"Supports only for V2 vTokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JumpRateModelV2.sol\":\"JumpRateModelV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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/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\"},\"contracts/BaseJumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { EXP_SCALE, MANTISSA_ONE } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Logic for Compound's JumpRateModel Contract V2.\\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\\n */\\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\\n /**\\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\\n */\\n uint256 public immutable blocksPerYear;\\n /**\\n * @notice The address of the AccessControlManager contract\\n */\\n IAccessControlManagerV8 public accessControlManager;\\n\\n /**\\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\\n */\\n uint256 public multiplierPerBlock;\\n\\n /**\\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\\n */\\n uint256 public baseRatePerBlock;\\n\\n /**\\n * @notice The multiplier per block after hitting a specified utilization point\\n */\\n uint256 public jumpMultiplierPerBlock;\\n\\n /**\\n * @notice The utilization point at which the jump multiplier is applied\\n */\\n uint256 public kink;\\n\\n event NewInterestParams(\\n uint256 baseRatePerBlock,\\n uint256 multiplierPerBlock,\\n uint256 jumpMultiplierPerBlock,\\n uint256 kink\\n );\\n\\n /**\\n * @notice Thrown when the action is prohibited by AccessControlManager\\n */\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Construct an interest rate model\\n * @param blocksPerYear_ The approximate number of blocks per year that is assumed by the interest rate model.\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @param accessControlManager_ The address of the AccessControlManager contract\\n */\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n ) {\\n require(address(accessControlManager_) != address(0), \\\"invalid ACM address\\\");\\n require(blocksPerYear_ != 0, \\\"Invalid blocks per year\\\");\\n accessControlManager = accessControlManager_;\\n blocksPerYear = blocksPerYear_;\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @custom:error Unauthorized if the sender is not allowed to call this function\\n * @custom:access Controlled by AccessControlManager\\n */\\n function updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) external virtual {\\n string memory signature = \\\"updateJumpRateModel(uint256,uint256,uint256,uint256)\\\";\\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Calculates the current supply rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param reserveFactorMantissa The current reserve factor for the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) public view virtual override returns (uint256) {\\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\\n uint256 incomeToDistribute = borrows * rateToPool;\\n uint256 supply = cash + borrows + badDebt - reserves;\\n return incomeToDistribute / supply;\\n }\\n\\n /**\\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market (currently unused)\\n * @param badDebt The amount of badDebt in the market\\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\\n */\\n function utilizationRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) public pure returns (uint256) {\\n // Utilization rate is 0 when there are no borrows and badDebt\\n if ((borrows + badDebt) == 0) {\\n return 0;\\n }\\n\\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\\n\\n if (rate > EXP_SCALE) {\\n rate = EXP_SCALE;\\n }\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Internal function to update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n */\\n function _updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) internal {\\n baseRatePerBlock = baseRatePerYear / blocksPerYear;\\n multiplierPerBlock = multiplierPerYear / blocksPerYear;\\n jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear;\\n kink = kink_;\\n\\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function _getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) internal view returns (uint256) {\\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\\n uint256 kink_ = kink;\\n\\n if (util <= kink_) {\\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n }\\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n uint256 excessUtil;\\n unchecked {\\n excessUtil = util - kink_;\\n }\\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\\n }\\n}\\n\",\"keccak256\":\"0xa2fa0aae39306f3c8ddf1c3b2fefffa15ce68406315cd95ebe2c2ac4263e7f16\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"contracts/JumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { BaseJumpRateModelV2 } from \\\"./BaseJumpRateModelV2.sol\\\";\\n\\n/**\\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\\n * @author Arr00\\n * @notice Supports only for V2 vTokens\\n */\\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n )\\n BaseJumpRateModelV2(\\n blocksPerYear_,\\n baseRatePerYear,\\n multiplierPerYear,\\n jumpMultiplierPerYear,\\n kink_,\\n accessControlManager_\\n )\\n /* solhint-disable-next-line no-empty-blocks */\\n {\\n\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view override returns (uint256) {\\n return _getBorrowRate(cash, borrows, reserves, badDebt);\\n }\\n}\\n\",\"keccak256\":\"0x4bac8ea1ed2dad59939317cc9e1a76fd55de6a745df29802f52cd97cf1c5a1ac\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b506040516109ca3803806109ca83398101604081905261002f916101a9565b8585858585856001600160a01b0381166100905760405162461bcd60e51b815260206004820152601360248201527f696e76616c69642041434d20616464726573730000000000000000000000000060448201526064015b60405180910390fd5b856000036100e05760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420626c6f636b732070657220796561720000000000000000006044820152606401610087565b600080546001600160a01b0319166001600160a01b038316179055608086905261010c8585858561011d565b50505050505050505050505061022f565b60805161012a908561020d565b60025560805161013a908461020d565b60015560805161014a908361020d565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b60008060008060008060c087890312156101c257600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b03811681146101ff57600080fd5b809150509295509295509295565b60008261022a57634e487b7160e01b600052601260045260246000fd5b500490565b60805161076b61025f6000396000818161012c0152818161046a0152818161049701526104c4015261076b6000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "devdoc": { + "author": "Arr00", + "kind": "dev", + "methods": { + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The borrow rate percentage per block as a mantissa (scaled by 1e18)" + } + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserveFactorMantissa": "The current reserve factor for the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)" + } + }, + "isInterestRateModel()": { + "returns": { + "_0": "Always true" + } + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized if the sender is not allowed to call this function", + "params": { + "baseRatePerYear": "The approximate target base APR, as a mantissa (scaled by EXP_SCALE)", + "jumpMultiplierPerYear": "The multiplierPerBlock after hitting a specified utilization point", + "kink_": "The utilization point at which the jump multiplier is applied", + "multiplierPerYear": "The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)" + } + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market (currently unused)" + }, + "returns": { + "_0": "The utilization rate as a mantissa between [0, MANTISSA_ONE]" + } + } + }, + "title": "Compound's JumpRateModel Contract V2 for V2 vTokens", + "version": 1 + }, + "userdoc": { + "errors": { + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ] + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "The address of the AccessControlManager contract" + }, + "baseRatePerBlock()": { + "notice": "The base interest rate which is the y-intercept when utilization rate is 0" + }, + "blocksPerYear()": { + "notice": "The approximate number of blocks per year that is assumed by the interest rate model" + }, + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current borrow rate per block" + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current supply rate per block" + }, + "isInterestRateModel()": { + "notice": "Indicator that this is an InterestRateModel contract (for inspection)" + }, + "jumpMultiplierPerBlock()": { + "notice": "The multiplier per block after hitting a specified utilization point" + }, + "kink()": { + "notice": "The utilization point at which the jump multiplier is applied" + }, + "multiplierPerBlock()": { + "notice": "The multiplier of utilization rate that gives the slope of the interest rate" + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "notice": "Update the parameters of the interest rate model" + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`" + } + }, + "notice": "Supports only for V2 vTokens", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7419, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "accessControlManager", + "offset": 0, + "slot": "0", + "type": "t_contract(IAccessControlManagerV8)5204" + }, + { + "astId": 7422, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "multiplierPerBlock", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 7425, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "baseRatePerBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 7428, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "jumpMultiplierPerBlock", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 7431, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "kink", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_contract(IAccessControlManagerV8)5204": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/JumpRateModelV2_base200bps_slope1500bps_jump30000bps_kink4500bps.json b/deployments/sepolia/JumpRateModelV2_base200bps_slope1500bps_jump30000bps_kink4500bps.json new file mode 100644 index 000000000..17ec3289e --- /dev/null +++ b/deployments/sepolia/JumpRateModelV2_base200bps_slope1500bps_jump30000bps_kink4500bps.json @@ -0,0 +1,519 @@ +{ + "address": "0x710F4044007a0e72e54626394462dB57d2d8479F", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xa1a3a80e811d7bfdf442162526790d8835456264854fe7d5d2a9a7ef4fb15939", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x710F4044007a0e72e54626394462dB57d2d8479F", + "transactionIndex": 51, + "gasUsed": "585088", + "logsBloom": "0x00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080001000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x79fd3e4ad550b91bfab01e685a7c348c6a4a3758fe3f83055c35751bb1eeef21", + "transactionHash": "0xa1a3a80e811d7bfdf442162526790d8835456264854fe7d5d2a9a7ef4fb15939", + "logs": [ + { + "transactionIndex": 51, + "blockNumber": 4776636, + "transactionHash": "0xa1a3a80e811d7bfdf442162526790d8835456264854fe7d5d2a9a7ef4fb15939", + "address": "0x710F4044007a0e72e54626394462dB57d2d8479F", + "topics": ["0x6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d"], + "data": "0x000000000000000000000000000000000000000000000000000000021136df940000000000000000000000000000000000000000000000000000000f811b8cdb0000000000000000000000000000000000000000000000000000013616270122000000000000000000000000000000000000000000000000063eb89da4ed0000", + "logIndex": 57, + "blockHash": "0x79fd3e4ad550b91bfab01e685a7c348c6a4a3758fe3f83055c35751bb1eeef21" + } + ], + "blockNumber": 4776636, + "cumulativeGasUsed": "6891174", + "status": 1, + "byzantium": true + }, + "args": [ + 2252571, + "20000000000000000", + "150000000000000000", + "3000000000000000000", + "450000000000000000", + "0xbf705C00578d43B6147ab4eaE04DBBEd1ccCdc96" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"},{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":false,\"internalType\":\"uint256\",\"name\":\"baseRatePerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"kink\",\"type\":\"uint256\"}],\"name\":\"NewInterestParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"jumpMultiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"kink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"multiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"}],\"name\":\"updateJumpRateModel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"utilizationRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Arr00\",\"kind\":\"dev\",\"methods\":{\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The borrow rate percentage per block as a mantissa (scaled by 1e18)\"}},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserveFactorMantissa\":\"The current reserve factor for the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\"}},\"isInterestRateModel()\":{\"returns\":{\"_0\":\"Always true\"}},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized if the sender is not allowed to call this function\",\"params\":{\"baseRatePerYear\":\"The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\",\"jumpMultiplierPerYear\":\"The multiplierPerBlock after hitting a specified utilization point\",\"kink_\":\"The utilization point at which the jump multiplier is applied\",\"multiplierPerYear\":\"The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\"}},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market (currently unused)\"},\"returns\":{\"_0\":\"The utilization rate as a mantissa between [0, MANTISSA_ONE]\"}}},\"title\":\"Compound's JumpRateModel Contract V2 for V2 vTokens\",\"version\":1},\"userdoc\":{\"errors\":{\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}]},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"The address of the AccessControlManager contract\"},\"baseRatePerBlock()\":{\"notice\":\"The base interest rate which is the y-intercept when utilization rate is 0\"},\"blocksPerYear()\":{\"notice\":\"The approximate number of blocks per year that is assumed by the interest rate model\"},\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current borrow rate per block\"},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current supply rate per block\"},\"isInterestRateModel()\":{\"notice\":\"Indicator that this is an InterestRateModel contract (for inspection)\"},\"jumpMultiplierPerBlock()\":{\"notice\":\"The multiplier per block after hitting a specified utilization point\"},\"kink()\":{\"notice\":\"The utilization point at which the jump multiplier is applied\"},\"multiplierPerBlock()\":{\"notice\":\"The multiplier of utilization rate that gives the slope of the interest rate\"},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"notice\":\"Update the parameters of the interest rate model\"},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\"}},\"notice\":\"Supports only for V2 vTokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JumpRateModelV2.sol\":\"JumpRateModelV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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/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\"},\"contracts/BaseJumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { EXP_SCALE, MANTISSA_ONE } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Logic for Compound's JumpRateModel Contract V2.\\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\\n */\\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\\n /**\\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\\n */\\n uint256 public immutable blocksPerYear;\\n /**\\n * @notice The address of the AccessControlManager contract\\n */\\n IAccessControlManagerV8 public accessControlManager;\\n\\n /**\\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\\n */\\n uint256 public multiplierPerBlock;\\n\\n /**\\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\\n */\\n uint256 public baseRatePerBlock;\\n\\n /**\\n * @notice The multiplier per block after hitting a specified utilization point\\n */\\n uint256 public jumpMultiplierPerBlock;\\n\\n /**\\n * @notice The utilization point at which the jump multiplier is applied\\n */\\n uint256 public kink;\\n\\n event NewInterestParams(\\n uint256 baseRatePerBlock,\\n uint256 multiplierPerBlock,\\n uint256 jumpMultiplierPerBlock,\\n uint256 kink\\n );\\n\\n /**\\n * @notice Thrown when the action is prohibited by AccessControlManager\\n */\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Construct an interest rate model\\n * @param blocksPerYear_ The approximate number of blocks per year that is assumed by the interest rate model.\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @param accessControlManager_ The address of the AccessControlManager contract\\n */\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n ) {\\n require(address(accessControlManager_) != address(0), \\\"invalid ACM address\\\");\\n require(blocksPerYear_ != 0, \\\"Invalid blocks per year\\\");\\n accessControlManager = accessControlManager_;\\n blocksPerYear = blocksPerYear_;\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @custom:error Unauthorized if the sender is not allowed to call this function\\n * @custom:access Controlled by AccessControlManager\\n */\\n function updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) external virtual {\\n string memory signature = \\\"updateJumpRateModel(uint256,uint256,uint256,uint256)\\\";\\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Calculates the current supply rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param reserveFactorMantissa The current reserve factor for the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) public view virtual override returns (uint256) {\\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\\n uint256 incomeToDistribute = borrows * rateToPool;\\n uint256 supply = cash + borrows + badDebt - reserves;\\n return incomeToDistribute / supply;\\n }\\n\\n /**\\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market (currently unused)\\n * @param badDebt The amount of badDebt in the market\\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\\n */\\n function utilizationRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) public pure returns (uint256) {\\n // Utilization rate is 0 when there are no borrows and badDebt\\n if ((borrows + badDebt) == 0) {\\n return 0;\\n }\\n\\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\\n\\n if (rate > EXP_SCALE) {\\n rate = EXP_SCALE;\\n }\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Internal function to update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n */\\n function _updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) internal {\\n baseRatePerBlock = baseRatePerYear / blocksPerYear;\\n multiplierPerBlock = multiplierPerYear / blocksPerYear;\\n jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear;\\n kink = kink_;\\n\\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function _getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) internal view returns (uint256) {\\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\\n uint256 kink_ = kink;\\n\\n if (util <= kink_) {\\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n }\\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n uint256 excessUtil;\\n unchecked {\\n excessUtil = util - kink_;\\n }\\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\\n }\\n}\\n\",\"keccak256\":\"0xa2fa0aae39306f3c8ddf1c3b2fefffa15ce68406315cd95ebe2c2ac4263e7f16\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"contracts/JumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { BaseJumpRateModelV2 } from \\\"./BaseJumpRateModelV2.sol\\\";\\n\\n/**\\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\\n * @author Arr00\\n * @notice Supports only for V2 vTokens\\n */\\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n )\\n BaseJumpRateModelV2(\\n blocksPerYear_,\\n baseRatePerYear,\\n multiplierPerYear,\\n jumpMultiplierPerYear,\\n kink_,\\n accessControlManager_\\n )\\n /* solhint-disable-next-line no-empty-blocks */\\n {\\n\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view override returns (uint256) {\\n return _getBorrowRate(cash, borrows, reserves, badDebt);\\n }\\n}\\n\",\"keccak256\":\"0x4bac8ea1ed2dad59939317cc9e1a76fd55de6a745df29802f52cd97cf1c5a1ac\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b506040516109ca3803806109ca83398101604081905261002f916101a9565b8585858585856001600160a01b0381166100905760405162461bcd60e51b815260206004820152601360248201527f696e76616c69642041434d20616464726573730000000000000000000000000060448201526064015b60405180910390fd5b856000036100e05760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420626c6f636b732070657220796561720000000000000000006044820152606401610087565b600080546001600160a01b0319166001600160a01b038316179055608086905261010c8585858561011d565b50505050505050505050505061022f565b60805161012a908561020d565b60025560805161013a908461020d565b60015560805161014a908361020d565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b60008060008060008060c087890312156101c257600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b03811681146101ff57600080fd5b809150509295509295509295565b60008261022a57634e487b7160e01b600052601260045260246000fd5b500490565b60805161076b61025f6000396000818161012c0152818161046a0152818161049701526104c4015261076b6000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "devdoc": { + "author": "Arr00", + "kind": "dev", + "methods": { + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The borrow rate percentage per block as a mantissa (scaled by 1e18)" + } + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserveFactorMantissa": "The current reserve factor for the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)" + } + }, + "isInterestRateModel()": { + "returns": { + "_0": "Always true" + } + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized if the sender is not allowed to call this function", + "params": { + "baseRatePerYear": "The approximate target base APR, as a mantissa (scaled by EXP_SCALE)", + "jumpMultiplierPerYear": "The multiplierPerBlock after hitting a specified utilization point", + "kink_": "The utilization point at which the jump multiplier is applied", + "multiplierPerYear": "The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)" + } + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market (currently unused)" + }, + "returns": { + "_0": "The utilization rate as a mantissa between [0, MANTISSA_ONE]" + } + } + }, + "title": "Compound's JumpRateModel Contract V2 for V2 vTokens", + "version": 1 + }, + "userdoc": { + "errors": { + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ] + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "The address of the AccessControlManager contract" + }, + "baseRatePerBlock()": { + "notice": "The base interest rate which is the y-intercept when utilization rate is 0" + }, + "blocksPerYear()": { + "notice": "The approximate number of blocks per year that is assumed by the interest rate model" + }, + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current borrow rate per block" + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current supply rate per block" + }, + "isInterestRateModel()": { + "notice": "Indicator that this is an InterestRateModel contract (for inspection)" + }, + "jumpMultiplierPerBlock()": { + "notice": "The multiplier per block after hitting a specified utilization point" + }, + "kink()": { + "notice": "The utilization point at which the jump multiplier is applied" + }, + "multiplierPerBlock()": { + "notice": "The multiplier of utilization rate that gives the slope of the interest rate" + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "notice": "Update the parameters of the interest rate model" + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`" + } + }, + "notice": "Supports only for V2 vTokens", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7419, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "accessControlManager", + "offset": 0, + "slot": "0", + "type": "t_contract(IAccessControlManagerV8)5204" + }, + { + "astId": 7422, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "multiplierPerBlock", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 7425, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "baseRatePerBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 7428, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "jumpMultiplierPerBlock", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 7431, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "kink", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_contract(IAccessControlManagerV8)5204": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json b/deployments/sepolia/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json new file mode 100644 index 000000000..774bf0917 --- /dev/null +++ b/deployments/sepolia/JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps.json @@ -0,0 +1,519 @@ +{ + "address": "0xaf5feAbe347BE5DF603CE63e45155bDb8049C78c", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + }, + { + "internalType": "contract IAccessControlManagerV8", + "name": "accessControlManager_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint256", + "name": "baseRatePerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "multiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jumpMultiplierPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "kink", + "type": "uint256" + } + ], + "name": "NewInterestParams", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "jumpMultiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "kink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "baseRatePerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "multiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "jumpMultiplierPerYear", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "kink_", + "type": "uint256" + } + ], + "name": "updateJumpRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cash", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "badDebt", + "type": "uint256" + } + ], + "name": "utilizationRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xf33e99d3b61d508aab350fcaa855ccd658bbe8354048432741041fff0919bb0a", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xaf5feAbe347BE5DF603CE63e45155bDb8049C78c", + "transactionIndex": 56, + "gasUsed": "585088", + "logsBloom": "0x00000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000002000000080000000000000000000000000000000000000000000000000000000000040000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x209c641fc9142107d76785f36d5575e8492196df409dec75d275e53ebc38b42c", + "transactionHash": "0xf33e99d3b61d508aab350fcaa855ccd658bbe8354048432741041fff0919bb0a", + "logs": [ + { + "transactionIndex": 56, + "blockNumber": 4776643, + "transactionHash": "0xf33e99d3b61d508aab350fcaa855ccd658bbe8354048432741041fff0919bb0a", + "address": "0xaf5feAbe347BE5DF603CE63e45155bDb8049C78c", + "topics": ["0x6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d"], + "data": "0x000000000000000000000000000000000000000000000000000000021136df9400000000000000000000000000000000000000000000000000000014ac24bbcf0000000000000000000000000000000000000000000000000000013616270122000000000000000000000000000000000000000000000000063eb89da4ed0000", + "logIndex": 55, + "blockHash": "0x209c641fc9142107d76785f36d5575e8492196df409dec75d275e53ebc38b42c" + } + ], + "blockNumber": 4776643, + "cumulativeGasUsed": "6672542", + "status": 1, + "byzantium": true + }, + "args": [ + 2252571, + "20000000000000000", + "200000000000000000", + "3000000000000000000", + "450000000000000000", + "0xbf705C00578d43B6147ab4eaE04DBBEd1ccCdc96" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"},{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":false,\"internalType\":\"uint256\",\"name\":\"baseRatePerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"kink\",\"type\":\"uint256\"}],\"name\":\"NewInterestParams\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"blocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getBorrowRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"getSupplyRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInterestRateModel\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"jumpMultiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"kink\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"multiplierPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"baseRatePerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"multiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jumpMultiplierPerYear\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"kink_\",\"type\":\"uint256\"}],\"name\":\"updateJumpRateModel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cash\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"badDebt\",\"type\":\"uint256\"}],\"name\":\"utilizationRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Arr00\",\"kind\":\"dev\",\"methods\":{\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The borrow rate percentage per block as a mantissa (scaled by 1e18)\"}},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserveFactorMantissa\":\"The current reserve factor for the market\",\"reserves\":\"The amount of reserves in the market\"},\"returns\":{\"_0\":\"The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\"}},\"isInterestRateModel()\":{\"returns\":{\"_0\":\"Always true\"}},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized if the sender is not allowed to call this function\",\"params\":{\"baseRatePerYear\":\"The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\",\"jumpMultiplierPerYear\":\"The multiplierPerBlock after hitting a specified utilization point\",\"kink_\":\"The utilization point at which the jump multiplier is applied\",\"multiplierPerYear\":\"The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\"}},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"params\":{\"badDebt\":\"The amount of badDebt in the market\",\"borrows\":\"The amount of borrows in the market\",\"cash\":\"The amount of cash in the market\",\"reserves\":\"The amount of reserves in the market (currently unused)\"},\"returns\":{\"_0\":\"The utilization rate as a mantissa between [0, MANTISSA_ONE]\"}}},\"title\":\"Compound's JumpRateModel Contract V2 for V2 vTokens\",\"version\":1},\"userdoc\":{\"errors\":{\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}]},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"The address of the AccessControlManager contract\"},\"baseRatePerBlock()\":{\"notice\":\"The base interest rate which is the y-intercept when utilization rate is 0\"},\"blocksPerYear()\":{\"notice\":\"The approximate number of blocks per year that is assumed by the interest rate model\"},\"getBorrowRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current borrow rate per block\"},\"getSupplyRate(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the current supply rate per block\"},\"isInterestRateModel()\":{\"notice\":\"Indicator that this is an InterestRateModel contract (for inspection)\"},\"jumpMultiplierPerBlock()\":{\"notice\":\"The multiplier per block after hitting a specified utilization point\"},\"kink()\":{\"notice\":\"The utilization point at which the jump multiplier is applied\"},\"multiplierPerBlock()\":{\"notice\":\"The multiplier of utilization rate that gives the slope of the interest rate\"},\"updateJumpRateModel(uint256,uint256,uint256,uint256)\":{\"notice\":\"Update the parameters of the interest rate model\"},\"utilizationRate(uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\"}},\"notice\":\"Supports only for V2 vTokens\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JumpRateModelV2.sol\":\"JumpRateModelV2\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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/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\"},\"contracts/BaseJumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { EXP_SCALE, MANTISSA_ONE } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Logic for Compound's JumpRateModel Contract V2.\\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\\n */\\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\\n /**\\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\\n */\\n uint256 public immutable blocksPerYear;\\n /**\\n * @notice The address of the AccessControlManager contract\\n */\\n IAccessControlManagerV8 public accessControlManager;\\n\\n /**\\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\\n */\\n uint256 public multiplierPerBlock;\\n\\n /**\\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\\n */\\n uint256 public baseRatePerBlock;\\n\\n /**\\n * @notice The multiplier per block after hitting a specified utilization point\\n */\\n uint256 public jumpMultiplierPerBlock;\\n\\n /**\\n * @notice The utilization point at which the jump multiplier is applied\\n */\\n uint256 public kink;\\n\\n event NewInterestParams(\\n uint256 baseRatePerBlock,\\n uint256 multiplierPerBlock,\\n uint256 jumpMultiplierPerBlock,\\n uint256 kink\\n );\\n\\n /**\\n * @notice Thrown when the action is prohibited by AccessControlManager\\n */\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Construct an interest rate model\\n * @param blocksPerYear_ The approximate number of blocks per year that is assumed by the interest rate model.\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @param accessControlManager_ The address of the AccessControlManager contract\\n */\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n ) {\\n require(address(accessControlManager_) != address(0), \\\"invalid ACM address\\\");\\n require(blocksPerYear_ != 0, \\\"Invalid blocks per year\\\");\\n accessControlManager = accessControlManager_;\\n blocksPerYear = blocksPerYear_;\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n * @custom:error Unauthorized if the sender is not allowed to call this function\\n * @custom:access Controlled by AccessControlManager\\n */\\n function updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) external virtual {\\n string memory signature = \\\"updateJumpRateModel(uint256,uint256,uint256,uint256)\\\";\\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n\\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\\n }\\n\\n /**\\n * @notice Calculates the current supply rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param reserveFactorMantissa The current reserve factor for the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) public view virtual override returns (uint256) {\\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\\n uint256 incomeToDistribute = borrows * rateToPool;\\n uint256 supply = cash + borrows + badDebt - reserves;\\n return incomeToDistribute / supply;\\n }\\n\\n /**\\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market (currently unused)\\n * @param badDebt The amount of badDebt in the market\\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\\n */\\n function utilizationRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) public pure returns (uint256) {\\n // Utilization rate is 0 when there are no borrows and badDebt\\n if ((borrows + badDebt) == 0) {\\n return 0;\\n }\\n\\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\\n\\n if (rate > EXP_SCALE) {\\n rate = EXP_SCALE;\\n }\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Internal function to update the parameters of the interest rate model\\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\\n * @param kink_ The utilization point at which the jump multiplier is applied\\n */\\n function _updateJumpRateModel(\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_\\n ) internal {\\n baseRatePerBlock = baseRatePerYear / blocksPerYear;\\n multiplierPerBlock = multiplierPerYear / blocksPerYear;\\n jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear;\\n kink = kink_;\\n\\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\\n */\\n function _getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) internal view returns (uint256) {\\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\\n uint256 kink_ = kink;\\n\\n if (util <= kink_) {\\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n }\\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\\n uint256 excessUtil;\\n unchecked {\\n excessUtil = util - kink_;\\n }\\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\\n }\\n}\\n\",\"keccak256\":\"0xa2fa0aae39306f3c8ddf1c3b2fefffa15ce68406315cd95ebe2c2ac4263e7f16\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"contracts/JumpRateModelV2.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { BaseJumpRateModelV2 } from \\\"./BaseJumpRateModelV2.sol\\\";\\n\\n/**\\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\\n * @author Arr00\\n * @notice Supports only for V2 vTokens\\n */\\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\\n constructor(\\n uint256 blocksPerYear_,\\n uint256 baseRatePerYear,\\n uint256 multiplierPerYear,\\n uint256 jumpMultiplierPerYear,\\n uint256 kink_,\\n IAccessControlManagerV8 accessControlManager_\\n )\\n BaseJumpRateModelV2(\\n blocksPerYear_,\\n baseRatePerYear,\\n multiplierPerYear,\\n jumpMultiplierPerYear,\\n kink_,\\n accessControlManager_\\n )\\n /* solhint-disable-next-line no-empty-blocks */\\n {\\n\\n }\\n\\n /**\\n * @notice Calculates the current borrow rate per block\\n * @param cash The amount of cash in the market\\n * @param borrows The amount of borrows in the market\\n * @param reserves The amount of reserves in the market\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view override returns (uint256) {\\n return _getBorrowRate(cash, borrows, reserves, badDebt);\\n }\\n}\\n\",\"keccak256\":\"0x4bac8ea1ed2dad59939317cc9e1a76fd55de6a745df29802f52cd97cf1c5a1ac\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b506040516109ca3803806109ca83398101604081905261002f916101a9565b8585858585856001600160a01b0381166100905760405162461bcd60e51b815260206004820152601360248201527f696e76616c69642041434d20616464726573730000000000000000000000000060448201526064015b60405180910390fd5b856000036100e05760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420626c6f636b732070657220796561720000000000000000006044820152606401610087565b600080546001600160a01b0319166001600160a01b038316179055608086905261010c8585858561011d565b50505050505050505050505061022f565b60805161012a908561020d565b60025560805161013a908461020d565b60015560805161014a908361020d565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b60008060008060008060c087890312156101c257600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b03811681146101ff57600080fd5b809150509295509295509295565b60008261022a57634e487b7160e01b600052601260045260246000fd5b500490565b60805161076b61025f6000396000818161012c0152818161046a0152818161049701526104c4015261076b6000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80638726bb89116100715780638726bb891461011e578063a385fb9614610127578063b4a0bdf31461014e578063b9f9850a14610179578063f14039de14610182578063fd2da3391461018b57600080fd5b8063073b8a74146100ae5780630cde8d1c146100d45780632037f3e7146100e75780632191f92a146100fc57806370d3c43f1461010b575b600080fd5b6100c16100bc366004610548565b610194565b6040519081526020015b60405180910390f35b6100c16100e236600461057a565b6101ad565b6100fa6100f5366004610548565b610240565b005b604051600181526020016100cb565b6100c1610119366004610548565b610317565b6100c160015481565b6100c17f000000000000000000000000000000000000000000000000000000000000000081565b600054610161906001600160a01b031681565b6040516001600160a01b0390911681526020016100cb565b6100c160035481565b6100c160025481565b6100c160045481565b60006101a2858585856103a0565b90505b949350505050565b6000806101c284670de0b6b3a76400006105cb565b905060006101d2888888876103a0565b90506000670de0b6b3a76400006101e984846105e2565b6101f39190610601565b90506000610201828a6105e2565b9050600088876102118c8e610623565b61021b9190610623565b61022591906105cb565b90506102318183610601565b9b9a5050505050505050505050565b600060405180606001604052806034815260200161070260349139600080546040516318c5e8ab60e01b815292935090916001600160a01b03909116906318c5e8ab906102939033908690600401610688565b602060405180830381865afa1580156102b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d491906106ac565b90508061030357333083604051634a3fa29360e01b81526004016102fa939291906106d5565b60405180910390fd5b61030f86868686610465565b505050505050565b60006103238285610623565b600003610332575060006101a5565b600083836103408789610623565b61034a9190610623565b61035491906105cb565b670de0b6b3a76400006103678588610623565b61037191906105e2565b61037b9190610601565b9050670de0b6b3a76400008111156101a25750670de0b6b3a764000095945050505050565b6000806103af86868686610317565b6004549091508082116103f357600254670de0b6b3a7640000600154846103d691906105e2565b6103e09190610601565b6103ea9190610623565b925050506101a5565b6000600254670de0b6b3a76400006001548461040f91906105e2565b6104199190610601565b6104239190610623565b90506000828403905081670de0b6b3a76400006003548361044491906105e2565b61044e9190610601565b6104589190610623565b9998505050505050505050565b61048f7f000000000000000000000000000000000000000000000000000000000000000085610601565b6002556104bc7f000000000000000000000000000000000000000000000000000000000000000084610601565b6001556104e97f000000000000000000000000000000000000000000000000000000000000000083610601565b60038190556004829055600254600154604080519283526020830191909152810191909152606081018290527f6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d9060800160405180910390a150505050565b6000806000806080858703121561055e57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a0868803121561059257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052601160045260246000fd5b6000828210156105dd576105dd6105b5565b500390565b60008160001904831182151516156105fc576105fc6105b5565b500290565b60008261061e57634e487b7160e01b600052601260045260246000fd5b500490565b60008219821115610636576106366105b5565b500190565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b81811115610673576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906101a59083018461063b565b6000602082840312156106be57600080fd5b815180151581146106ce57600080fd5b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906101a29083018461063b56fe7570646174654a756d70526174654d6f64656c2875696e743235362c75696e743235362c75696e743235362c75696e7432353629a2646970667358221220b75bf1d0074ed366d2d57edf624e0b49ebdf2d5a91d67cfcef99da40658b1d9864736f6c634300080d0033", + "devdoc": { + "author": "Arr00", + "kind": "dev", + "methods": { + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The borrow rate percentage per block as a mantissa (scaled by 1e18)" + } + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserveFactorMantissa": "The current reserve factor for the market", + "reserves": "The amount of reserves in the market" + }, + "returns": { + "_0": "The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)" + } + }, + "isInterestRateModel()": { + "returns": { + "_0": "Always true" + } + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized if the sender is not allowed to call this function", + "params": { + "baseRatePerYear": "The approximate target base APR, as a mantissa (scaled by EXP_SCALE)", + "jumpMultiplierPerYear": "The multiplierPerBlock after hitting a specified utilization point", + "kink_": "The utilization point at which the jump multiplier is applied", + "multiplierPerYear": "The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)" + } + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "params": { + "badDebt": "The amount of badDebt in the market", + "borrows": "The amount of borrows in the market", + "cash": "The amount of cash in the market", + "reserves": "The amount of reserves in the market (currently unused)" + }, + "returns": { + "_0": "The utilization rate as a mantissa between [0, MANTISSA_ONE]" + } + } + }, + "title": "Compound's JumpRateModel Contract V2 for V2 vTokens", + "version": 1 + }, + "userdoc": { + "errors": { + "Unauthorized(address,address,string)": [ + { + "notice": "Thrown when the action is prohibited by AccessControlManager" + } + ] + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "The address of the AccessControlManager contract" + }, + "baseRatePerBlock()": { + "notice": "The base interest rate which is the y-intercept when utilization rate is 0" + }, + "blocksPerYear()": { + "notice": "The approximate number of blocks per year that is assumed by the interest rate model" + }, + "getBorrowRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current borrow rate per block" + }, + "getSupplyRate(uint256,uint256,uint256,uint256,uint256)": { + "notice": "Calculates the current supply rate per block" + }, + "isInterestRateModel()": { + "notice": "Indicator that this is an InterestRateModel contract (for inspection)" + }, + "jumpMultiplierPerBlock()": { + "notice": "The multiplier per block after hitting a specified utilization point" + }, + "kink()": { + "notice": "The utilization point at which the jump multiplier is applied" + }, + "multiplierPerBlock()": { + "notice": "The multiplier of utilization rate that gives the slope of the interest rate" + }, + "updateJumpRateModel(uint256,uint256,uint256,uint256)": { + "notice": "Update the parameters of the interest rate model" + }, + "utilizationRate(uint256,uint256,uint256,uint256)": { + "notice": "Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`" + } + }, + "notice": "Supports only for V2 vTokens", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7419, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "accessControlManager", + "offset": 0, + "slot": "0", + "type": "t_contract(IAccessControlManagerV8)5204" + }, + { + "astId": 7422, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "multiplierPerBlock", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 7425, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "baseRatePerBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 7428, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "jumpMultiplierPerBlock", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 7431, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "kink", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_contract(IAccessControlManagerV8)5204": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/MockCRV.json b/deployments/sepolia/MockCRV.json new file mode 100644 index 000000000..054cb9cae --- /dev/null +++ b/deployments/sepolia/MockCRV.json @@ -0,0 +1,450 @@ +{ + "address": "0x2c78EF7eab67A6e0C9cAa6f2821929351bdDF3d3", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x311706e934d3770d68109cede5a55c52b0102f9fc758ca704f42019a6cc78adc", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x2c78EF7eab67A6e0C9cAa6f2821929351bdDF3d3", + "transactionIndex": 0, + "gasUsed": "636288", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x092bb23b5e60068cd3658fa1f2188bf4e360ee4dd874909fcd1f1cf7ca58657e", + "transactionHash": "0x311706e934d3770d68109cede5a55c52b0102f9fc758ca704f42019a6cc78adc", + "logs": [], + "blockNumber": 4614369, + "cumulativeGasUsed": "636288", + "status": 1, + "byzantium": true + }, + "args": ["Curve DAO Token", "CRV", 18], + "numDeployments": 1, + "solcInputHash": "2bf9f23321dda7abe5f536a221df7bce", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"faucet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Mocks/MockToken.sol\":\"MockToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"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\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/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(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {\\n _decimals = decimals_;\\n }\\n\\n function faucet(uint256 amount) external {\\n _mint(msg.sender, amount);\\n }\\n\\n function decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x60985130406108e7c07e140da7ba3c71f94ae0fbb658cffdeee7758fc2f33a8d\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162000c4838038062000c488339810160408190526200003491620001e8565b8251839083906200004d90600390602085019062000075565b5080516200006390600490602084019062000075565b50505060ff1660805250620002a99050565b82805462000083906200026d565b90600052602060002090601f016020900481019282620000a75760008555620000f2565b82601f10620000c257805160ff1916838001178555620000f2565b82800160010185558215620000f2579182015b82811115620000f2578251825591602001919060010190620000d5565b506200010092915062000104565b5090565b5b8082111562000100576000815560010162000105565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014357600080fd5b81516001600160401b03808211156200016057620001606200011b565b604051601f8301601f19908116603f011681019082821181831017156200018b576200018b6200011b565b81604052838152602092508683858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b83821115620001de5760008385830101525b9695505050505050565b600080600060608486031215620001fe57600080fd5b83516001600160401b03808211156200021657600080fd5b620002248783880162000131565b945060208601519150808211156200023b57600080fd5b506200024a8682870162000131565b925050604084015160ff811681146200026257600080fd5b809150509250925092565b600181811c908216806200028257607f821691505b602082108103620002a357634e487b7160e01b600052602260045260246000fd5b50919050565b608051610983620002c5600039600061012601526109836000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea26469706673582212200edbd9e1418eb52e2d269095e1f96654d0216eaadc9e1421f9f01d70e09ac4fa64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea26469706673582212200edbd9e1418eb52e2d269095e1f96654d0216eaadc9e1421f9f01d70e09ac4fa64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2454, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 2460, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 2462, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 2464, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 2466, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "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_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/MockUSDC.json b/deployments/sepolia/MockUSDC.json new file mode 100644 index 000000000..82855578d --- /dev/null +++ b/deployments/sepolia/MockUSDC.json @@ -0,0 +1,450 @@ +{ + "address": "0x772d68929655ce7234C8C94256526ddA66Ef641E", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xbd68674b1714c20e124249ade9f7cb55a4888e3e52dc17b6e6d158e471f48e7d", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0x772d68929655ce7234C8C94256526ddA66Ef641E", + "transactionIndex": 0, + "gasUsed": "636216", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbb36c067993b5437463d80eaac64f6bcc210c7e9fcc8778a448ca0e888a999c0", + "transactionHash": "0xbd68674b1714c20e124249ade9f7cb55a4888e3e52dc17b6e6d158e471f48e7d", + "logs": [], + "blockNumber": 4312877, + "cumulativeGasUsed": "636216", + "status": 1, + "byzantium": true + }, + "args": ["USD Coin", "USDC", 6], + "numDeployments": 1, + "solcInputHash": "8249036c2fd27f6f9b40677e2c950aaf", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"faucet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Mocks/MockToken.sol\":\"MockToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"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\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/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 decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x12742c274df06975fbf8e8a23a1adc14ff9475ac7276be6b1b6e86260caca60a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162000c4838038062000c488339810160408190526200003491620001e8565b8251839083906200004d90600390602085019062000075565b5080516200006390600490602084019062000075565b50505060ff1660805250620002a99050565b82805462000083906200026d565b90600052602060002090601f016020900481019282620000a75760008555620000f2565b82601f10620000c257805160ff1916838001178555620000f2565b82800160010185558215620000f2579182015b82811115620000f2578251825591602001919060010190620000d5565b506200010092915062000104565b5090565b5b8082111562000100576000815560010162000105565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014357600080fd5b81516001600160401b03808211156200016057620001606200011b565b604051601f8301601f19908116603f011681019082821181831017156200018b576200018b6200011b565b81604052838152602092508683858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b83821115620001de5760008385830101525b9695505050505050565b600080600060608486031215620001fe57600080fd5b83516001600160401b03808211156200021657600080fd5b620002248783880162000131565b945060208601519150808211156200023b57600080fd5b506200024a8682870162000131565b925050604084015160ff811681146200026257600080fd5b809150509250925092565b600181811c908216806200028257607f821691505b602082108103620002a357634e487b7160e01b600052602260045260246000fd5b50919050565b608051610983620002c5600039600061012601526109836000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220ad3749d07ad778d94ced64a644949d79ddd48e1fb7564746812dce99fc30b8ce64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220ad3749d07ad778d94ced64a644949d79ddd48e1fb7564746812dce99fc30b8ce64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2454, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 2460, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 2462, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 2464, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 2466, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "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_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/MockUSDT.json b/deployments/sepolia/MockUSDT.json new file mode 100644 index 000000000..0a4361a5f --- /dev/null +++ b/deployments/sepolia/MockUSDT.json @@ -0,0 +1,450 @@ +{ + "address": "0x8d412FD0bc5d826615065B931171Eed10F5AF266", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x8d0cc21a795d98af7c6ccc9bacc73f0df8389b93eb05cbe75eed227848d4f005", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0x8d412FD0bc5d826615065B931171Eed10F5AF266", + "transactionIndex": 0, + "gasUsed": "636240", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc5d86a5dd3042b012288885c7f71384896f9dd45d3a005530ef19c186f2ddbbf", + "transactionHash": "0x8d0cc21a795d98af7c6ccc9bacc73f0df8389b93eb05cbe75eed227848d4f005", + "logs": [], + "blockNumber": 4312876, + "cumulativeGasUsed": "636240", + "status": 1, + "byzantium": true + }, + "args": ["Tether USD", "USDT", 6], + "numDeployments": 1, + "solcInputHash": "8249036c2fd27f6f9b40677e2c950aaf", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"faucet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Mocks/MockToken.sol\":\"MockToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"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\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/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 decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x12742c274df06975fbf8e8a23a1adc14ff9475ac7276be6b1b6e86260caca60a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162000c4838038062000c488339810160408190526200003491620001e8565b8251839083906200004d90600390602085019062000075565b5080516200006390600490602084019062000075565b50505060ff1660805250620002a99050565b82805462000083906200026d565b90600052602060002090601f016020900481019282620000a75760008555620000f2565b82601f10620000c257805160ff1916838001178555620000f2565b82800160010185558215620000f2579182015b82811115620000f2578251825591602001919060010190620000d5565b506200010092915062000104565b5090565b5b8082111562000100576000815560010162000105565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014357600080fd5b81516001600160401b03808211156200016057620001606200011b565b604051601f8301601f19908116603f011681019082821181831017156200018b576200018b6200011b565b81604052838152602092508683858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b83821115620001de5760008385830101525b9695505050505050565b600080600060608486031215620001fe57600080fd5b83516001600160401b03808211156200021657600080fd5b620002248783880162000131565b945060208601519150808211156200023b57600080fd5b506200024a8682870162000131565b925050604084015160ff811681146200026257600080fd5b809150509250925092565b600181811c908216806200028257607f821691505b602082108103620002a357634e487b7160e01b600052602260045260246000fd5b50919050565b608051610983620002c5600039600061012601526109836000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220ad3749d07ad778d94ced64a644949d79ddd48e1fb7564746812dce99fc30b8ce64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220ad3749d07ad778d94ced64a644949d79ddd48e1fb7564746812dce99fc30b8ce64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2454, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 2460, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 2462, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 2464, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 2466, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "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_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/MockWBTC.json b/deployments/sepolia/MockWBTC.json new file mode 100644 index 000000000..8b872cfef --- /dev/null +++ b/deployments/sepolia/MockWBTC.json @@ -0,0 +1,450 @@ +{ + "address": "0x92A2928f5634BEa89A195e7BeCF0f0FEEDAB885b", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x8c0f9ef25038a33e74fb0f7dcdc6d48e761d465ca247f6223b4e1341d48bf32f", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0x92A2928f5634BEa89A195e7BeCF0f0FEEDAB885b", + "transactionIndex": 0, + "gasUsed": "636252", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe6f12a84fd739f969d314b5a979490393b1b57531b3d65edd3593acf516171d6", + "transactionHash": "0x8c0f9ef25038a33e74fb0f7dcdc6d48e761d465ca247f6223b4e1341d48bf32f", + "logs": [], + "blockNumber": 4312874, + "cumulativeGasUsed": "636252", + "status": 1, + "byzantium": true + }, + "args": ["Wrapped BTC", "WBTC", 8], + "numDeployments": 1, + "solcInputHash": "8249036c2fd27f6f9b40677e2c950aaf", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"faucet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Mocks/MockToken.sol\":\"MockToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"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\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/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 decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x12742c274df06975fbf8e8a23a1adc14ff9475ac7276be6b1b6e86260caca60a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162000c4838038062000c488339810160408190526200003491620001e8565b8251839083906200004d90600390602085019062000075565b5080516200006390600490602084019062000075565b50505060ff1660805250620002a99050565b82805462000083906200026d565b90600052602060002090601f016020900481019282620000a75760008555620000f2565b82601f10620000c257805160ff1916838001178555620000f2565b82800160010185558215620000f2579182015b82811115620000f2578251825591602001919060010190620000d5565b506200010092915062000104565b5090565b5b8082111562000100576000815560010162000105565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014357600080fd5b81516001600160401b03808211156200016057620001606200011b565b604051601f8301601f19908116603f011681019082821181831017156200018b576200018b6200011b565b81604052838152602092508683858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b83821115620001de5760008385830101525b9695505050505050565b600080600060608486031215620001fe57600080fd5b83516001600160401b03808211156200021657600080fd5b620002248783880162000131565b945060208601519150808211156200023b57600080fd5b506200024a8682870162000131565b925050604084015160ff811681146200026257600080fd5b809150509250925092565b600181811c908216806200028257607f821691505b602082108103620002a357634e487b7160e01b600052602260045260246000fd5b50919050565b608051610983620002c5600039600061012601526109836000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220ad3749d07ad778d94ced64a644949d79ddd48e1fb7564746812dce99fc30b8ce64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220ad3749d07ad778d94ced64a644949d79ddd48e1fb7564746812dce99fc30b8ce64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2454, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 2460, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 2462, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 2464, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 2466, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "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_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/MockWETH.json b/deployments/sepolia/MockWETH.json new file mode 100644 index 000000000..12e68e60b --- /dev/null +++ b/deployments/sepolia/MockWETH.json @@ -0,0 +1,450 @@ +{ + "address": "0x700868CAbb60e90d77B6588ce072d9859ec8E281", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x51aeaec8b0a621a5de1d4b44a3239f46d6b77f3dfea2cbb0fa42f65e36eae73b", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0x700868CAbb60e90d77B6588ce072d9859ec8E281", + "transactionIndex": 0, + "gasUsed": "636276", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x4bb63e3f12b30283eec63ff2401cd7a269797f11cd80aab45cffa321696dcd73", + "transactionHash": "0x51aeaec8b0a621a5de1d4b44a3239f46d6b77f3dfea2cbb0fa42f65e36eae73b", + "logs": [], + "blockNumber": 4312875, + "cumulativeGasUsed": "636276", + "status": 1, + "byzantium": true + }, + "args": ["Wrapped Ether", "WETH", 18], + "numDeployments": 1, + "solcInputHash": "8249036c2fd27f6f9b40677e2c950aaf", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"faucet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Mocks/MockToken.sol\":\"MockToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"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\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/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 decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x12742c274df06975fbf8e8a23a1adc14ff9475ac7276be6b1b6e86260caca60a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162000c4838038062000c488339810160408190526200003491620001e8565b8251839083906200004d90600390602085019062000075565b5080516200006390600490602084019062000075565b50505060ff1660805250620002a99050565b82805462000083906200026d565b90600052602060002090601f016020900481019282620000a75760008555620000f2565b82601f10620000c257805160ff1916838001178555620000f2565b82800160010185558215620000f2579182015b82811115620000f2578251825591602001919060010190620000d5565b506200010092915062000104565b5090565b5b8082111562000100576000815560010162000105565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014357600080fd5b81516001600160401b03808211156200016057620001606200011b565b604051601f8301601f19908116603f011681019082821181831017156200018b576200018b6200011b565b81604052838152602092508683858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b83821115620001de5760008385830101525b9695505050505050565b600080600060608486031215620001fe57600080fd5b83516001600160401b03808211156200021657600080fd5b620002248783880162000131565b945060208601519150808211156200023b57600080fd5b506200024a8682870162000131565b925050604084015160ff811681146200026257600080fd5b809150509250925092565b600181811c908216806200028257607f821691505b602082108103620002a357634e487b7160e01b600052602260045260246000fd5b50919050565b608051610983620002c5600039600061012601526109836000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220ad3749d07ad778d94ced64a644949d79ddd48e1fb7564746812dce99fc30b8ce64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220ad3749d07ad778d94ced64a644949d79ddd48e1fb7564746812dce99fc30b8ce64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2454, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 2460, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 2462, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 2464, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 2466, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "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_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/MockcrvUSD.json b/deployments/sepolia/MockcrvUSD.json new file mode 100644 index 000000000..a2b764640 --- /dev/null +++ b/deployments/sepolia/MockcrvUSD.json @@ -0,0 +1,450 @@ +{ + "address": "0x36421d873abCa3E2bE6BB3c819C0CF26374F63b6", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "faucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x5142d5b4abbac6e4036e6c292d03fcc4e337c73e8a7b91b8a65fb6de344ac852", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x36421d873abCa3E2bE6BB3c819C0CF26374F63b6", + "transactionIndex": 0, + "gasUsed": "636420", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x768f116786a80f75e6bf8a83b9dd68c612bd8975a3255839a6747eeedbc8645c", + "transactionHash": "0x5142d5b4abbac6e4036e6c292d03fcc4e337c73e8a7b91b8a65fb6de344ac852", + "logs": [], + "blockNumber": 4614370, + "cumulativeGasUsed": "636420", + "status": 1, + "byzantium": true + }, + "args": ["Curve.Fi USD Stablecoin", "crvUSD", 18], + "numDeployments": 1, + "solcInputHash": "2bf9f23321dda7abe5f536a221df7bce", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"faucet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/Mocks/MockToken.sol\":\"MockToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0xa56ca923f70c1748830700250b19c61b70db9a683516dc5e216694a50445d99c\",\"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\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/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(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {\\n _decimals = decimals_;\\n }\\n\\n function faucet(uint256 amount) external {\\n _mint(msg.sender, amount);\\n }\\n\\n function decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x60985130406108e7c07e140da7ba3c71f94ae0fbb658cffdeee7758fc2f33a8d\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a06040523480156200001157600080fd5b5060405162000c4838038062000c488339810160408190526200003491620001e8565b8251839083906200004d90600390602085019062000075565b5080516200006390600490602084019062000075565b50505060ff1660805250620002a99050565b82805462000083906200026d565b90600052602060002090601f016020900481019282620000a75760008555620000f2565b82601f10620000c257805160ff1916838001178555620000f2565b82800160010185558215620000f2579182015b82811115620000f2578251825591602001919060010190620000d5565b506200010092915062000104565b5090565b5b8082111562000100576000815560010162000105565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014357600080fd5b81516001600160401b03808211156200016057620001606200011b565b604051601f8301601f19908116603f011681019082821181831017156200018b576200018b6200011b565b81604052838152602092508683858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b83821115620001de5760008385830101525b9695505050505050565b600080600060608486031215620001fe57600080fd5b83516001600160401b03808211156200021657600080fd5b620002248783880162000131565b945060208601519150808211156200023b57600080fd5b506200024a8682870162000131565b925050604084015160ff811681146200026257600080fd5b809150509250925092565b600181811c908216806200028257607f821691505b602082108103620002a357634e487b7160e01b600052602260045260246000fd5b50919050565b608051610983620002c5600039600061012601526109836000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea26469706673582212200edbd9e1418eb52e2d269095e1f96654d0216eaadc9e1421f9f01d70e09ac4fa64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80635791589711610071578063579158971461016357806370a082311461017857806395d89b41146101a1578063a457c2d7146101a9578063a9059cbb146101bc578063dd62ed3e146101cf57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f5780633950935114610150575b600080fd5b6100c16101e2565b6040516100ce91906107a8565b60405180910390f35b6100ea6100e5366004610819565b610274565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610843565b61028c565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ce565b6100ea61015e366004610819565b6102b0565b61017661017136600461087f565b6102d2565b005b6100fe610186366004610898565b6001600160a01b031660009081526020819052604090205490565b6100c16102df565b6100ea6101b7366004610819565b6102ee565b6100ea6101ca366004610819565b61036e565b6100fe6101dd3660046108ba565b61037c565b6060600380546101f1906108ed565b80601f016020809104026020016040519081016040528092919081815260200182805461021d906108ed565b801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b6000336102828185856103a7565b5060019392505050565b60003361029a8582856104cb565b6102a5858585610545565b506001949350505050565b6000336102828185856102c3838361037c565b6102cd9190610927565b6103a7565b6102dc33826106e9565b50565b6060600480546101f1906108ed565b600033816102fc828661037c565b9050838110156103615760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a582868684036103a7565b600033610282818585610545565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104095760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610358565b6001600160a01b03821661046a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610358565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104d7848461037c565b9050600019811461053f57818110156105325760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610358565b61053f84848484036103a7565b50505050565b6001600160a01b0383166105a95760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610358565b6001600160a01b03821661060b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610358565b6001600160a01b038316600090815260208190526040902054818110156106835760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610358565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361053f565b6001600160a01b03821661073f5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610358565b80600260008282546107519190610927565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107d5578581018301518582016040015282016107b9565b818111156107e7576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461081457600080fd5b919050565b6000806040838503121561082c57600080fd5b610835836107fd565b946020939093013593505050565b60008060006060848603121561085857600080fd5b610861846107fd565b925061086f602085016107fd565b9150604084013590509250925092565b60006020828403121561089157600080fd5b5035919050565b6000602082840312156108aa57600080fd5b6108b3826107fd565b9392505050565b600080604083850312156108cd57600080fd5b6108d6836107fd565b91506108e4602084016107fd565b90509250929050565b600181811c9082168061090157607f821691505b60208210810361092157634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561094857634e487b7160e01b600052601160045260246000fd5b50019056fea26469706673582212200edbd9e1418eb52e2d269095e1f96654d0216eaadc9e1421f9f01d70e09ac4fa64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2454, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 2460, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 2462, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 2464, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 2466, + "contract": "contracts/test/Mocks/MockToken.sol:MockToken", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "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_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/sepolia/PoolLens.json b/deployments/sepolia/PoolLens.json new file mode 100644 index 000000000..0a911e419 --- /dev/null +++ b/deployments/sepolia/PoolLens.json @@ -0,0 +1,1274 @@ +{ + "address": "0xC319C2E53a5f732ebF0eb87b14F56B53bdc3446b", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + } + ], + "name": "getAllPools", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + }, + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "address", + "name": "priceOracle", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata[]", + "name": "vTokens", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.PoolData[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "comptrollerAddress", + "type": "address" + } + ], + "name": "getPendingRewards", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "distributorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "totalRewards", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.PendingReward[]", + "name": "pendingRewards", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.RewardSummary[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptrollerAddress", + "type": "address" + } + ], + "name": "getPoolBadDebt", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "totalBadDebtUsd", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "badDebtUsd", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.BadDebt[]", + "name": "badDebts", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.BadDebtSummary", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolByComptroller", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + }, + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "address", + "name": "priceOracle", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata[]", + "name": "vTokens", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.PoolData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "venusPool", + "type": "tuple" + } + ], + "name": "getPoolDataFromVenusPool", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + }, + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "address", + "name": "priceOracle", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata[]", + "name": "vTokens", + "type": "tuple[]" + } + ], + "internalType": "struct PoolLens.PoolData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPoolsSupportedByAsset", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getVTokenForAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "vTokenBalances", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUnderlying", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenAllowance", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenBalances", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "vTokenBalancesAll", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balanceOf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalanceCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "balanceOfUnderlying", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenAllowance", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenBalances[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "vTokenMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "vTokenMetadataAll", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exchangeRateCurrent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowRatePerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCaps", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalCash", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "address", + "name": "underlyingAssetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vTokenDecimals", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenMetadata[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "vTokenUnderlyingPrice", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "underlyingPrice", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenUnderlyingPrice", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "vTokenUnderlyingPriceAll", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "underlyingPrice", + "type": "uint256" + } + ], + "internalType": "struct PoolLens.VTokenUnderlyingPrice[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x2cdfc4ba2ebb2279abd874a8bb03700931f9049029ed1c06785147059b3de38d", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xC319C2E53a5f732ebF0eb87b14F56B53bdc3446b", + "transactionIndex": 31, + "gasUsed": "3384332", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x59cb986fa386b6bdd147349b06247f3531f112ca612c9c053d5533c58e8a0c03", + "transactionHash": "0x2cdfc4ba2ebb2279abd874a8bb03700931f9049029ed1c06785147059b3de38d", + "logs": [], + "blockNumber": 4776617, + "cumulativeGasUsed": "7422493", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"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/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.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"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/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/protocol-reserve/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/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor is changed by admin\\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow.\\n * @param vTokenAddress The address of the asset to be removed\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return NO_ERROR;\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\n _checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = accountAssets[user];\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = accountAssets[borrower];\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n _ensureMaxLoops(numMarkets);\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Enables forced liquidations for a market. If forced liquidation is enabled,\\n * borrows in the market may be liquidated regardless of the account liquidity\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall Hypothetical account shortfall below collateral requirements\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Check if a market is marked as listed (active)\\n * @param vToken vToken Address for the market to check\\n * @return listed True if listed otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].isListed;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n VToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the market specified, otherwise false.\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = accountAssets[account];\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n }\\n\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = accountAssets[account];\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x42f9cceba5f1b4d82047f930a7049740d13ab36004bb1a58b462b9e111c08665\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x44c67531518072db11bf6eafe29499073724346a7855579b09a9da049742d879\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // Multiplier representing the most one can borrow against their collateral in this market.\\n // For instance, 0.9 to allow borrowing 90% of collateral value.\\n // Must be between 0 and 1, and stored as a mantissa.\\n uint256 collateralFactorMantissa;\\n // Multiplier representing the collateralization after which the borrow is eligible\\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n // value. Must be between 0 and collateral factor, stored as a mantissa.\\n uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\n enum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n }\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint256 public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n /**\\n * @notice Official mapping of vTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\\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\":\"0xdfc033911c20e09516110ae3f94740b4be1a065baee4412a708e25a25568eac8\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x3f8ec4e18bca1fdf8619966f4f6e095e205517a78f8c741b87fe82125754f96f\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x1f17b8e3fdd89657d488250140f6d6abeb04f2b822467139687487f9c1dbe397\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlock;\\n uint256 borrowRatePerBlock;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = comptroller.getAllMarkets();\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\n\\n return\\n VTokenBalances({\\n vToken: address(vToken),\\n balanceOf: balanceOf,\\n borrowBalanceCurrent: borrowBalanceCurrent,\\n balanceOfUnderlying: balanceOfUnderlying,\\n tokenBalance: tokenBalance,\\n tokenAllowance: tokenAllowance\\n });\\n }\\n\\n /**\\n * @notice Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n return\\n VTokenMetadata({\\n vToken: address(vToken),\\n exchangeRateCurrent: exchangeRateCurrent,\\n supplyRatePerBlock: vToken.supplyRatePerBlock(),\\n borrowRatePerBlock: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(address(vToken.comptroller()));\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n return\\n VTokenUnderlyingPrice({\\n vToken: address(vToken),\\n underlyingPrice: priceOracle.getUnderlyingPrice(address(vToken))\\n });\\n }\\n\\n function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n (borrowState.index, borrowState.block, borrowState.lastRewardingBlock) = rewardsDistributor\\n .rewardTokenBorrowState(address(markets[i]));\\n RewardTokenState memory supplyState;\\n (supplyState.index, supplyState.block, supplyState.lastRewardingBlock) = rewardsDistributor\\n .rewardTokenSupplyState(address(markets[i]));\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumber = block.number;\\n\\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\\n blockNumber = borrowState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(blockNumber, uint256(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, borrowAmount) : Double({ mantissa: 0 });\\n Double memory index = add_(Double({ mantissa: borrowState.index }), ratio);\\n borrowState.index = safe224(index.mantissa, \\\"new index overflows\\\");\\n borrowState.block = safe32(blockNumber, \\\"block number overflows\\\");\\n } else if (deltaBlocks > 0) {\\n borrowState.block = safe32(blockNumber, \\\"block number overflows\\\");\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumber = block.number;\\n\\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\\n blockNumber = supplyState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(blockNumber, uint256(supplyState.block));\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, supplyTokens) : Double({ mantissa: 0 });\\n Double memory index = add_(Double({ mantissa: supplyState.index }), ratio);\\n supplyState.index = safe224(index.mantissa, \\\"new index overflows\\\");\\n supplyState.block = safe32(blockNumber, \\\"block number overflows\\\");\\n } else if (deltaBlocks > 0) {\\n supplyState.block = safe32(blockNumber, \\\"block number overflows\\\");\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0x2807e00ed5f2dfd063317d9595ae6fa7b25b3ef83fe12c2d5dee27da59cee841\",\"license\":\"BSD-3-Clause\"},\"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\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\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\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\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 /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.approve(vTokenAddress, 0);\\n underlying.approve(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0x425c5d620fab58b88132a2b00a5d20789fae4f79bd7795d00861be7b3625d4dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title PoolRegistryInterface\\n * @author Venus\\n * @notice Interface implemented by `PoolRegistry`.\\n */\\ninterface PoolRegistryInterface {\\n /**\\n * @notice Struct for a Venus interest rate pool.\\n */\\n struct VenusPool {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n }\\n\\n /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7e8ccd190ef019a3f8c3fcb67ed3eadd7bed32b263f88566870d138cd95ae312\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each block for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller private comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlock(address[],uint32[],uint32[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumber();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\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 */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumber = getBlockNumber();\\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n function getBlockNumber() public view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumber();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplyIndex = supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowIndex = borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\\n blockNumber = supplyState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\\n\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n supplyState.index = safe224(\\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n supplyState.block = blockNumber;\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\\n blockNumber = borrowState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n borrowState.index = safe224(\\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n borrowState.block = blockNumber;\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0x598aad1a12d6a895f82a8b619000099efe53994fe89522b41adaa68819fac652\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n /**\\n * Reentrancy Guard **\\n */\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\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 /**\\n * @notice Construct a new money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\n );\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n _borrowFresh(msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == _getBlockNumber()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockDelta block difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockDelta;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return amount The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return rate The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this v\\n * @return rate The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number */\\n uint256 currentBlockNumber = _getBlockNumber();\\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentBlockNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n _reduceReservesFresh(totalReservesNew);\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is sending the assets for supply\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `_doTransferIn` for the minter and the mintAmount.\\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n }\\n\\n /**\\n * @notice User redeems vTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n */\\n function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\\n * On success, the vToken has redeemAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(redeemer, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrower User who borrows the assets\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the borrower and the borrowAmount.\\n * On success, the vToken borrowAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(borrower, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call _doTransferIn for the payer and the repayAmount\\n * On success, the vToken holds an additional repayAmount of cash.\\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == NO_ERROR, \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetInterestRateModelFreshCheck();\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n }\\n\\n /**\\n * Safe Token **\\n */\\n\\n /**\\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\\n * This function returns the actual amount received,\\n * which may be less than `amount` if there is a fee attached to the transfer.\\n * @param from Sender of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n * @return Actual amount received\\n */\\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n // Return the amount that was *actually* transferred\\n return balanceAfter - balanceBefore;\\n }\\n\\n /**\\n * @dev Just a regular ERC-20 transfer, reverts on failure\\n * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n _setComptroller(comptroller_);\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = _getBlockNumber();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying tokens owned by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n * @return Current block number\\n */\\n function _getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xf4f49f4a1718a36a7cbd413e959d957eade62d4ad96c0ebde4562e53cac72f7e\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\n\\n // Maximum borrow rate that can ever be applied (.0005% / block)\\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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[48] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves block delta is changed\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x777842977e2441dd79f4781ff61f431dda351c3d33862e40063ef58d03b489a1\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x909eb76841ebd57d8f53686b76b1a09da7bbbbcddb29510c41674d5aa84c713e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613c41806100206000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c80637a27db571161008c578063aa5dbd2311610066578063aa5dbd23146101fb578063b31242391461021b578063d77ebf961461023b578063e0a67f111461025b57600080fd5b80637a27db571461019b5780637c51b642146101bb5780637c84e3b3146101db57600080fd5b80630d3ae318146100d45780631f884fdf146100fd578063345954dc1461011d5780633e3e399c1461013d57806347d86a811461015d57806355dd951514610170575b600080fd5b6100e76100e2366004612cfb565b61027b565b6040516100f49190613068565b60405180910390f35b61011061010b3660046130c6565b6105b0565b6040516100f49190613107565b61013061012b366004613167565b610681565b6040516100f49190613184565b61015061014b366004613167565b6107bd565b6040516100f491906131e6565b6100e761016b366004613270565b610b38565b61018361017e3660046132a9565b610bbf565b6040516001600160a01b0390911681526020016100f4565b6101ae6101a9366004613270565b610c3f565b6040516100f491906132f4565b6101ce6101c93660046133ce565b610f55565b6040516100f49190613459565b6101ee6101e9366004613167565b611017565b6040516100f491906134a7565b61020e610209366004613167565b611181565b6040516100f491906134c7565b61022e610229366004613270565b611806565b6040516100f491906134d6565b61024e610249366004613270565b611aed565b6040516100f491906134e4565b61026e610269366004613548565b611b60565b6040516100f491906135e1565b610283612ac9565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102cc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102f49190810190613624565b9050600061030182611b60565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa158015610354573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261037c91908101906136f7565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610435573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045991906137ab565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c991906137c8565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561050c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053091906137c8565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610573573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059791906137c8565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b038111156105cd576105cd612c44565b60405190808252806020026020018201604052801561061257816020015b60408051808201909152600080825260208201528152602001906001900390816105eb5790505b50905060005b828110156106785761064a868683818110610635576106356137e1565b90506020020160208101906101e99190613167565b82828151811061065c5761065c6137e1565b6020026020010181905250806106719061380d565b9050610618565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa1580156106c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106f091908101906138a9565b80519091506000816001600160401b0381111561070f5761070f612c44565b60405190808252806020026020018201604052801561074857816020015b610735612ac9565b81526020019060019003908161072d5790505b50905060005b828110156107b357600084828151811061076a5761076a6137e1565b602002602001015190506000610780898361027b565b905080848481518110610795576107956137e1565b60200260200101819052505050806107ac9061380d565b905061074e565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561081f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108479190810190613624565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610889573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ad91906137ab565b9050600082516001600160401b038111156108ca576108ca612c44565b60405190808252806020026020018201604052801561090f57816020015b60408051808201909152600080825260208201528152602001906001900390816108e85790505b50905061093f604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b24576040805180820190915260008082526020820152858281518110610984576109846137e1565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d3576109d36137e1565b60200260200101516040518263ffffffff1660e01b8152600401610a0691906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4791906137c8565b878481518110610a5957610a596137e1565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac291906137c8565b610acc9190613959565b610ad69190613978565b60208201526040830151805182919084908110610af557610af56137e1565b6020026020010181905250806020015188610b10919061399a565b97505080610b1d9061380d565b9050610955565b506020810195909552509295945050505050565b610b40612ac9565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610bb791839190821690637aee632d90602401600060405180830381865afa158015610b8f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526100e291908101906139b2565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3691906137ab565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c81573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ca99190810190613624565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610ceb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d1391908101906139e6565b9050600081516001600160401b03811115610d3057610d30612c44565b604051908082528060200260200182016040528015610d8157816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610d4e5790505b50905060005b82518110156107b3576040805160808101825260008082526020820181905291810191909152606080820152838281518110610dc557610dc56137e1565b60209081029190910101516001600160a01b031681528351849083908110610def57610def6137e1565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5891906137ab565b6001600160a01b031660208201528351849083908110610e7a57610e7a6137e1565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610ecc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef091906137c8565b816040018181525050610f1d8886868581518110610f1057610f106137e1565b6020026020010151611c1e565b816060018190525080838381518110610f3857610f386137e1565b60200260200101819052505080610f4e9061380d565b9050610d87565b6060826000816001600160401b03811115610f7257610f72612c44565b604051908082528060200260200182016040528015610fab57816020015b610f98612b4c565b815260200190600190039081610f905790505b50905060005b828110156107b357610fe9878783818110610fce57610fce6137e1565b9050602002016020810190610fe39190613167565b86611806565b828281518110610ffb57610ffb6137e1565b6020026020010181905250806110109061380d565b9050610fb1565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561106b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108f91906137ab565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f591906137ab565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa158015611153573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117791906137c8565b9052949350505050565b611189612b8b565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ed91906137c8565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561122f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125391906137ab565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa1580156112a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c69190613a74565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561130a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132e91906137ab565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611370573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113949190613aa7565b60ff1690506040518061020001604052808a6001600160a01b031681526020018881526020018a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141c91906137c8565b81526020018a6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa15801561145f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148391906137c8565b81526020018a6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ea91906137c8565b81526040516302c3bcbb60e01b81526001600160a01b038c811660048301526020909201918816906302c3bcbb90602401602060405180830381865afa158015611538573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155c91906137c8565b815260405163252c221960e11b81526001600160a01b038c81166004830152602090920191881690634a58443290602401602060405180830381865afa1580156115aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ce91906137c8565b81526020018a6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611611573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163591906137c8565b81526020018a6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169c91906137c8565b81526020018a6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170391906137c8565b81526020018a6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176a91906137c8565b81526020018515158152602001848152602001836001600160a01b031681526020018a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ee9190613aa7565b60ff1681526020019190915298975050505050505050565b61180e612b4c565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611858573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187c91906137c8565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af11580156118ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ee91906137c8565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af115801561193c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196091906137c8565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c991906137ab565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611a13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3791906137c8565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aad91906137c8565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611b38573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bb79190810190613aca565b80516060906000816001600160401b03811115611b7f57611b7f612c44565b604051908082528060200260200182016040528015611bb857816020015b611ba5612b8b565b815260200190600190039081611b9d5790505b50905060005b82811015611c1657611be8858281518110611bdb57611bdb6137e1565b6020026020010151611181565b828281518110611bfa57611bfa6137e1565b602002602001018190525080611c0f9061380d565b9050611bbe565b509392505050565b6060600083516001600160401b03811115611c3b57611c3b612c44565b604051908082528060200260200182016040528015611c8057816020015b6040805180820190915260008082526020820152815260200190600190039081611c595790505b50905060005b8451811015610678576040805160608101825260008082526020820181905291810191909152846001600160a01b0316632c427b57878481518110611ccd57611ccd6137e1565b60200260200101516040518263ffffffff1660e01b8152600401611d0091906001600160a01b0391909116815260200190565b606060405180830381865afa158015611d1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d419190613b83565b63ffffffff90811660408501521660208301526001600160e01b03168152611d82604080516060810182526000808252602082018190529181019190915290565b856001600160a01b03166392a18235888581518110611da357611da36137e1565b60200260200101516040518263ffffffff1660e01b8152600401611dd691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e179190613b83565b63ffffffff90811660408086019190915291166020808501919091526001600160e01b0390921683528051918201905287516000919081908a9087908110611e6157611e616137e1565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eca91906137c8565b8152509050611ef4888581518110611ee457611ee46137e1565b6020026020010151888584611fef565b611f18888581518110611f0957611f096137e1565b60200260200101518884612277565b6000611f40898681518110611f2f57611f2f6137e1565b6020026020010151898c87866124f5565b90506000611f698a8781518110611f5957611f596137e1565b60200260200101518a8d87612725565b60408051808201909152600080825260208201529091508a8781518110611f9257611f926137e1565b60209081029190910101516001600160a01b03168152611fb2828461399a565b602082015287518190899089908110611fcd57611fcd6137e1565b602002602001018190525050505050505080611fe89061380d565b9050611c86565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa158015612039573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205d91906137c8565b6040840151909150439063ffffffff16158015906120845750836040015163ffffffff1681115b156120965750604083015163ffffffff165b60006120ac82866020015163ffffffff16612949565b90506000811180156120be5750600083115b15612224576000612130886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015612106573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212a91906137c8565b8661295c565b9050600061213e838661297a565b9050600080831161215e5760405180602001604052806000815250612168565b6121688284612986565b9050600061219160405180602001604052808b600001516001600160e01b0316815250836129cb565b90506121cc8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b8152506129f7565b6001600160e01b03168952604080518082019091526016815275626c6f636b206e756d626572206f766572666c6f777360501b602082015261220f908790612a33565b63ffffffff1660208a01525061226e92505050565b801561226e576122628260405180604001604052806016815260200175626c6f636b206e756d626572206f766572666c6f777360501b815250612a33565b63ffffffff1660208601525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa1580156122c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e591906137c8565b6040830151909150439063ffffffff161580159061230c5750826040015163ffffffff1681115b1561231e5750604082015163ffffffff165b600061233482856020015163ffffffff16612949565b90506000811180156123465750600083115b156124a3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561238b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123af91906137c8565b905060006123bd838661297a565b905060008083116123dd57604051806020016040528060008152506123e7565b6123e78284612986565b9050600061241060405180602001604052808a600001516001600160e01b0316815250836129cb565b905061244b8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b8152506129f7565b6001600160e01b03168852604080518082019091526016815275626c6f636b206e756d626572206f766572666c6f777360501b602082015261248e908790612a33565b63ffffffff166020890152506124ed92505050565b80156124ed576124e18260405180604001604052806016815260200175626c6f636b206e756d626572206f766572666c6f777360501b815250612a33565b63ffffffff1660208501525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa158015612568573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258c91906137c8565b9052805190915015801561260e5750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125fd9190613bc6565b6001600160e01b0316826000015110155b1561268157866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612651573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126759190613bc6565b6001600160e01b031681525b600061268d8383612a5b565b6040516395dd919360e01b81526001600160a01b03898116600483015291925060009161270891908c16906395dd919390602401602060405180830381865afa1580156126de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270291906137c8565b8761295c565b905060006127168284612a87565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127bc91906137c8565b9052805190915015801561283e5750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282d9190613bc6565b6001600160e01b0316826000015110155b156128b157856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a59190613bc6565b6001600160e01b031681525b60006128bd8383612a5b565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612909573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061292d91906137c8565b9050600061293b8284612a87565b9a9950505050505050505050565b60006129558284613be1565b9392505050565b600061295561297384670de0b6b3a764000061297a565b8351612ab1565b60006129558284613959565b60408051602081019091526000815260405180602001604052806129c26129bc866ec097ce7bc90715b34b9f100000000061297a565b85612ab1565b90529392505050565b60408051602081019091526000815260405180602001604052806129c285600001518560000151612abd565b6000816001600160e01b03841115612a2b5760405162461bcd60e51b8152600401612a229190613bf8565b60405180910390fd5b509192915050565b60008163ffffffff841115612a2b5760405162461bcd60e51b8152600401612a229190613bf8565b60408051602081019091526000815260405180602001604052806129c285600001518560000151612949565b60006ec097ce7bc90715b34b9f1000000000612aa784846000015161297a565b6129559190613978565b60006129558284613978565b6000612955828461399a565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610200016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b0316815260200160008152602001600081525090565b6001600160a01b0381168114612c3157600080fd5b50565b8035612c3f81612c1c565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612c7c57612c7c612c44565b60405290565b604051606081016001600160401b0381118282101715612c7c57612c7c612c44565b604051601f8201601f191681016001600160401b0381118282101715612ccc57612ccc612c44565b604052919050565b60006001600160401b03821115612ced57612ced612c44565b50601f01601f191660200190565b60008060408385031215612d0e57600080fd5b8235612d1981612c1c565b91506020838101356001600160401b0380821115612d3657600080fd5b9085019060a08288031215612d4a57600080fd5b612d52612c5a565b823582811115612d6157600080fd5b83019150601f82018813612d7457600080fd5b8135612d87612d8282612cd4565b612ca4565b8181528986838601011115612d9b57600080fd5b818685018783013760008683830101528083525050612dbb848401612c34565b84820152612dcb60408401612c34565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612e0d578181015183820152602001612df5565b83811115612e1c576000848401525b50505050565b60008151808452612e3a816020860160208601612df2565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e083015261010080820151818401525061012080820151818401525061014080820151818401525061016080820151612ed98285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e090810151910152565b600081518084526020808501945080840160005b83811015612f4c57612f38878351612e4e565b610200969096019590820190600101612f25565b509495945050505050565b60006101a08251818552612f6d82860182612e22565b9150506020830151612f8a60208601826001600160a01b03169052565b506040830151612fa560408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a0860152612fd18282612e22565b91505060c083015184820360c0860152612feb8282612e22565b91505060e083015184820360e08601526130058282612e22565b91505061010080840151613023828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261305e8382612f11565b9695505050505050565b6020815260006129556020830184612f57565b60008083601f84011261308d57600080fd5b5081356001600160401b038111156130a457600080fd5b6020830191508360208260051b85010111156130bf57600080fd5b9250929050565b600080602083850312156130d957600080fd5b82356001600160401b038111156130ef57600080fd5b6130fb8582860161307b565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561315a5761314a84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613124565b5091979650505050505050565b60006020828403121561317957600080fd5b813561295581612c1c565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156131d957603f198886030184526131c7858351612f57565b945092850192908501906001016131ab565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156132645761325082865180516001600160a01b03168252602090810151910152565b93850193600193909301929082019061322a565b50979650505050505050565b6000806040838503121561328357600080fd5b823561328e81612c1c565b9150602083013561329e81612c1c565b809150509250929050565b6000806000606084860312156132be57600080fd5b83356132c981612c1c565b925060208401356132d981612c1c565b915060408401356132e981612c1c565b809150509250925092565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b848110156133bf57898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156133aa5761339683855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613370565b5050968901969450509187019160010161331c565b50919998505050505050505050565b6000806000604084860312156133e357600080fd5b83356001600160401b038111156133f957600080fd5b6134058682870161307b565b90945092505060208401356132e981612c1c565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561349b57613488838551613419565b9284019260c09290920191600101613475565b50909695505050505050565b81516001600160a01b0316815260208083015190820152604081016105aa565b61020081016105aa8284612e4e565b60c081016105aa8284613419565b6020808252825182820181905260009190848201906040850190845b8181101561349b5783516001600160a01b031683529284019291840191600101613500565b60006001600160401b0382111561353e5761353e612c44565b5060051b60200190565b6000602080838503121561355b57600080fd5b82356001600160401b0381111561357157600080fd5b8301601f8101851361358257600080fd5b8035613590612d8282613525565b81815260059190911b820183019083810190878311156135af57600080fd5b928401925b828410156135d65783356135c781612c1c565b825292840192908401906135b4565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561349b57613610838551612e4e565b9284019261020092909201916001016135fd565b6000602080838503121561363757600080fd5b82516001600160401b0381111561364d57600080fd5b8301601f8101851361365e57600080fd5b805161366c612d8282613525565b81815260059190911b8201830190838101908783111561368b57600080fd5b928401925b828410156135d65783516136a381612c1c565b82529284019290840190613690565b600082601f8301126136c357600080fd5b81516136d1612d8282612cd4565b8181528460208386010111156136e657600080fd5b610bb7826020830160208701612df2565b60006020828403121561370957600080fd5b81516001600160401b038082111561372057600080fd5b908301906060828603121561373457600080fd5b61373c612c82565b82518281111561374b57600080fd5b613757878286016136b2565b82525060208301518281111561376c57600080fd5b613778878286016136b2565b60208301525060408301518281111561379057600080fd5b61379c878286016136b2565b60408301525095945050505050565b6000602082840312156137bd57600080fd5b815161295581612c1c565b6000602082840312156137da57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161381f5761381f6137f7565b5060010190565b600060a0828403121561383857600080fd5b613840612c5a565b905081516001600160401b0381111561385857600080fd5b613864848285016136b2565b825250602082015161387581612c1c565b6020820152604082015161388881612c1c565b80604083015250606082015160608201526080820151608082015292915050565b600060208083850312156138bc57600080fd5b82516001600160401b03808211156138d357600080fd5b818501915085601f8301126138e757600080fd5b81516138f5612d8282613525565b81815260059190911b8301840190848101908883111561391457600080fd5b8585015b8381101561394c578051858111156139305760008081fd5b61393e8b89838a0101613826565b845250918601918601613918565b5098975050505050505050565b6000816000190483118215151615613973576139736137f7565b500290565b60008261399557634e487b7160e01b600052601260045260246000fd5b500490565b600082198211156139ad576139ad6137f7565b500190565b6000602082840312156139c457600080fd5b81516001600160401b038111156139da57600080fd5b610bb784828501613826565b600060208083850312156139f957600080fd5b82516001600160401b03811115613a0f57600080fd5b8301601f81018513613a2057600080fd5b8051613a2e612d8282613525565b81815260059190911b82018301908381019087831115613a4d57600080fd5b928401925b828410156135d6578351613a6581612c1c565b82529284019290840190613a52565b60008060408385031215613a8757600080fd5b82518015158114613a9757600080fd5b6020939093015192949293505050565b600060208284031215613ab957600080fd5b815160ff8116811461295557600080fd5b60006020808385031215613add57600080fd5b82516001600160401b03811115613af357600080fd5b8301601f81018513613b0457600080fd5b8051613b12612d8282613525565b81815260059190911b82018301908381019087831115613b3157600080fd5b928401925b828410156135d6578351613b4981612c1c565b82529284019290840190613b36565b80516001600160e01b0381168114612c3f57600080fd5b805163ffffffff81168114612c3f57600080fd5b600080600060608486031215613b9857600080fd5b613ba184613b58565b9250613baf60208501613b6f565b9150613bbd60408501613b6f565b90509250925092565b600060208284031215613bd857600080fd5b61295582613b58565b600082821015613bf357613bf36137f7565b500390565b6020815260006129556020830184612e2256fea2646970667358221220779aa170654683bfa5d56af49287aad0533e05083a4a11a6cf8812add9dcb69064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80637a27db571161008c578063aa5dbd2311610066578063aa5dbd23146101fb578063b31242391461021b578063d77ebf961461023b578063e0a67f111461025b57600080fd5b80637a27db571461019b5780637c51b642146101bb5780637c84e3b3146101db57600080fd5b80630d3ae318146100d45780631f884fdf146100fd578063345954dc1461011d5780633e3e399c1461013d57806347d86a811461015d57806355dd951514610170575b600080fd5b6100e76100e2366004612cfb565b61027b565b6040516100f49190613068565b60405180910390f35b61011061010b3660046130c6565b6105b0565b6040516100f49190613107565b61013061012b366004613167565b610681565b6040516100f49190613184565b61015061014b366004613167565b6107bd565b6040516100f491906131e6565b6100e761016b366004613270565b610b38565b61018361017e3660046132a9565b610bbf565b6040516001600160a01b0390911681526020016100f4565b6101ae6101a9366004613270565b610c3f565b6040516100f491906132f4565b6101ce6101c93660046133ce565b610f55565b6040516100f49190613459565b6101ee6101e9366004613167565b611017565b6040516100f491906134a7565b61020e610209366004613167565b611181565b6040516100f491906134c7565b61022e610229366004613270565b611806565b6040516100f491906134d6565b61024e610249366004613270565b611aed565b6040516100f491906134e4565b61026e610269366004613548565b611b60565b6040516100f491906135e1565b610283612ac9565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102cc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102f49190810190613624565b9050600061030182611b60565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa158015610354573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261037c91908101906136f7565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610435573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045991906137ab565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c991906137c8565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561050c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053091906137c8565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610573573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059791906137c8565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b038111156105cd576105cd612c44565b60405190808252806020026020018201604052801561061257816020015b60408051808201909152600080825260208201528152602001906001900390816105eb5790505b50905060005b828110156106785761064a868683818110610635576106356137e1565b90506020020160208101906101e99190613167565b82828151811061065c5761065c6137e1565b6020026020010181905250806106719061380d565b9050610618565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa1580156106c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106f091908101906138a9565b80519091506000816001600160401b0381111561070f5761070f612c44565b60405190808252806020026020018201604052801561074857816020015b610735612ac9565b81526020019060019003908161072d5790505b50905060005b828110156107b357600084828151811061076a5761076a6137e1565b602002602001015190506000610780898361027b565b905080848481518110610795576107956137e1565b60200260200101819052505050806107ac9061380d565b905061074e565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561081f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108479190810190613624565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610889573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ad91906137ab565b9050600082516001600160401b038111156108ca576108ca612c44565b60405190808252806020026020018201604052801561090f57816020015b60408051808201909152600080825260208201528152602001906001900390816108e85790505b50905061093f604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b24576040805180820190915260008082526020820152858281518110610984576109846137e1565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d3576109d36137e1565b60200260200101516040518263ffffffff1660e01b8152600401610a0691906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4791906137c8565b878481518110610a5957610a596137e1565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac291906137c8565b610acc9190613959565b610ad69190613978565b60208201526040830151805182919084908110610af557610af56137e1565b6020026020010181905250806020015188610b10919061399a565b97505080610b1d9061380d565b9050610955565b506020810195909552509295945050505050565b610b40612ac9565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610bb791839190821690637aee632d90602401600060405180830381865afa158015610b8f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526100e291908101906139b2565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3691906137ab565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c81573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ca99190810190613624565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610ceb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d1391908101906139e6565b9050600081516001600160401b03811115610d3057610d30612c44565b604051908082528060200260200182016040528015610d8157816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610d4e5790505b50905060005b82518110156107b3576040805160808101825260008082526020820181905291810191909152606080820152838281518110610dc557610dc56137e1565b60209081029190910101516001600160a01b031681528351849083908110610def57610def6137e1565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5891906137ab565b6001600160a01b031660208201528351849083908110610e7a57610e7a6137e1565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610ecc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef091906137c8565b816040018181525050610f1d8886868581518110610f1057610f106137e1565b6020026020010151611c1e565b816060018190525080838381518110610f3857610f386137e1565b60200260200101819052505080610f4e9061380d565b9050610d87565b6060826000816001600160401b03811115610f7257610f72612c44565b604051908082528060200260200182016040528015610fab57816020015b610f98612b4c565b815260200190600190039081610f905790505b50905060005b828110156107b357610fe9878783818110610fce57610fce6137e1565b9050602002016020810190610fe39190613167565b86611806565b828281518110610ffb57610ffb6137e1565b6020026020010181905250806110109061380d565b9050610fb1565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561106b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108f91906137ab565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f591906137ab565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa158015611153573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117791906137c8565b9052949350505050565b611189612b8b565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ed91906137c8565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561122f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125391906137ab565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa1580156112a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c69190613a74565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561130a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132e91906137ab565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611370573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113949190613aa7565b60ff1690506040518061020001604052808a6001600160a01b031681526020018881526020018a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141c91906137c8565b81526020018a6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa15801561145f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148391906137c8565b81526020018a6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ea91906137c8565b81526040516302c3bcbb60e01b81526001600160a01b038c811660048301526020909201918816906302c3bcbb90602401602060405180830381865afa158015611538573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155c91906137c8565b815260405163252c221960e11b81526001600160a01b038c81166004830152602090920191881690634a58443290602401602060405180830381865afa1580156115aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ce91906137c8565b81526020018a6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611611573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163591906137c8565b81526020018a6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169c91906137c8565b81526020018a6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170391906137c8565b81526020018a6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176a91906137c8565b81526020018515158152602001848152602001836001600160a01b031681526020018a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ee9190613aa7565b60ff1681526020019190915298975050505050505050565b61180e612b4c565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611858573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187c91906137c8565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af11580156118ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ee91906137c8565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af115801561193c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196091906137c8565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c991906137ab565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611a13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3791906137c8565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aad91906137c8565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611b38573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bb79190810190613aca565b80516060906000816001600160401b03811115611b7f57611b7f612c44565b604051908082528060200260200182016040528015611bb857816020015b611ba5612b8b565b815260200190600190039081611b9d5790505b50905060005b82811015611c1657611be8858281518110611bdb57611bdb6137e1565b6020026020010151611181565b828281518110611bfa57611bfa6137e1565b602002602001018190525080611c0f9061380d565b9050611bbe565b509392505050565b6060600083516001600160401b03811115611c3b57611c3b612c44565b604051908082528060200260200182016040528015611c8057816020015b6040805180820190915260008082526020820152815260200190600190039081611c595790505b50905060005b8451811015610678576040805160608101825260008082526020820181905291810191909152846001600160a01b0316632c427b57878481518110611ccd57611ccd6137e1565b60200260200101516040518263ffffffff1660e01b8152600401611d0091906001600160a01b0391909116815260200190565b606060405180830381865afa158015611d1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d419190613b83565b63ffffffff90811660408501521660208301526001600160e01b03168152611d82604080516060810182526000808252602082018190529181019190915290565b856001600160a01b03166392a18235888581518110611da357611da36137e1565b60200260200101516040518263ffffffff1660e01b8152600401611dd691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e179190613b83565b63ffffffff90811660408086019190915291166020808501919091526001600160e01b0390921683528051918201905287516000919081908a9087908110611e6157611e616137e1565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eca91906137c8565b8152509050611ef4888581518110611ee457611ee46137e1565b6020026020010151888584611fef565b611f18888581518110611f0957611f096137e1565b60200260200101518884612277565b6000611f40898681518110611f2f57611f2f6137e1565b6020026020010151898c87866124f5565b90506000611f698a8781518110611f5957611f596137e1565b60200260200101518a8d87612725565b60408051808201909152600080825260208201529091508a8781518110611f9257611f926137e1565b60209081029190910101516001600160a01b03168152611fb2828461399a565b602082015287518190899089908110611fcd57611fcd6137e1565b602002602001018190525050505050505080611fe89061380d565b9050611c86565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa158015612039573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205d91906137c8565b6040840151909150439063ffffffff16158015906120845750836040015163ffffffff1681115b156120965750604083015163ffffffff165b60006120ac82866020015163ffffffff16612949565b90506000811180156120be5750600083115b15612224576000612130886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015612106573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212a91906137c8565b8661295c565b9050600061213e838661297a565b9050600080831161215e5760405180602001604052806000815250612168565b6121688284612986565b9050600061219160405180602001604052808b600001516001600160e01b0316815250836129cb565b90506121cc8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b8152506129f7565b6001600160e01b03168952604080518082019091526016815275626c6f636b206e756d626572206f766572666c6f777360501b602082015261220f908790612a33565b63ffffffff1660208a01525061226e92505050565b801561226e576122628260405180604001604052806016815260200175626c6f636b206e756d626572206f766572666c6f777360501b815250612a33565b63ffffffff1660208601525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa1580156122c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e591906137c8565b6040830151909150439063ffffffff161580159061230c5750826040015163ffffffff1681115b1561231e5750604082015163ffffffff165b600061233482856020015163ffffffff16612949565b90506000811180156123465750600083115b156124a3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561238b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123af91906137c8565b905060006123bd838661297a565b905060008083116123dd57604051806020016040528060008152506123e7565b6123e78284612986565b9050600061241060405180602001604052808a600001516001600160e01b0316815250836129cb565b905061244b8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b8152506129f7565b6001600160e01b03168852604080518082019091526016815275626c6f636b206e756d626572206f766572666c6f777360501b602082015261248e908790612a33565b63ffffffff166020890152506124ed92505050565b80156124ed576124e18260405180604001604052806016815260200175626c6f636b206e756d626572206f766572666c6f777360501b815250612a33565b63ffffffff1660208501525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa158015612568573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258c91906137c8565b9052805190915015801561260e5750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125fd9190613bc6565b6001600160e01b0316826000015110155b1561268157866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612651573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126759190613bc6565b6001600160e01b031681525b600061268d8383612a5b565b6040516395dd919360e01b81526001600160a01b03898116600483015291925060009161270891908c16906395dd919390602401602060405180830381865afa1580156126de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270291906137c8565b8761295c565b905060006127168284612a87565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127bc91906137c8565b9052805190915015801561283e5750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282d9190613bc6565b6001600160e01b0316826000015110155b156128b157856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a59190613bc6565b6001600160e01b031681525b60006128bd8383612a5b565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612909573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061292d91906137c8565b9050600061293b8284612a87565b9a9950505050505050505050565b60006129558284613be1565b9392505050565b600061295561297384670de0b6b3a764000061297a565b8351612ab1565b60006129558284613959565b60408051602081019091526000815260405180602001604052806129c26129bc866ec097ce7bc90715b34b9f100000000061297a565b85612ab1565b90529392505050565b60408051602081019091526000815260405180602001604052806129c285600001518560000151612abd565b6000816001600160e01b03841115612a2b5760405162461bcd60e51b8152600401612a229190613bf8565b60405180910390fd5b509192915050565b60008163ffffffff841115612a2b5760405162461bcd60e51b8152600401612a229190613bf8565b60408051602081019091526000815260405180602001604052806129c285600001518560000151612949565b60006ec097ce7bc90715b34b9f1000000000612aa784846000015161297a565b6129559190613978565b60006129558284613978565b6000612955828461399a565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610200016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b0316815260200160008152602001600081525090565b6001600160a01b0381168114612c3157600080fd5b50565b8035612c3f81612c1c565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612c7c57612c7c612c44565b60405290565b604051606081016001600160401b0381118282101715612c7c57612c7c612c44565b604051601f8201601f191681016001600160401b0381118282101715612ccc57612ccc612c44565b604052919050565b60006001600160401b03821115612ced57612ced612c44565b50601f01601f191660200190565b60008060408385031215612d0e57600080fd5b8235612d1981612c1c565b91506020838101356001600160401b0380821115612d3657600080fd5b9085019060a08288031215612d4a57600080fd5b612d52612c5a565b823582811115612d6157600080fd5b83019150601f82018813612d7457600080fd5b8135612d87612d8282612cd4565b612ca4565b8181528986838601011115612d9b57600080fd5b818685018783013760008683830101528083525050612dbb848401612c34565b84820152612dcb60408401612c34565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612e0d578181015183820152602001612df5565b83811115612e1c576000848401525b50505050565b60008151808452612e3a816020860160208601612df2565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e083015261010080820151818401525061012080820151818401525061014080820151818401525061016080820151612ed98285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e090810151910152565b600081518084526020808501945080840160005b83811015612f4c57612f38878351612e4e565b610200969096019590820190600101612f25565b509495945050505050565b60006101a08251818552612f6d82860182612e22565b9150506020830151612f8a60208601826001600160a01b03169052565b506040830151612fa560408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a0860152612fd18282612e22565b91505060c083015184820360c0860152612feb8282612e22565b91505060e083015184820360e08601526130058282612e22565b91505061010080840151613023828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261305e8382612f11565b9695505050505050565b6020815260006129556020830184612f57565b60008083601f84011261308d57600080fd5b5081356001600160401b038111156130a457600080fd5b6020830191508360208260051b85010111156130bf57600080fd5b9250929050565b600080602083850312156130d957600080fd5b82356001600160401b038111156130ef57600080fd5b6130fb8582860161307b565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561315a5761314a84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613124565b5091979650505050505050565b60006020828403121561317957600080fd5b813561295581612c1c565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156131d957603f198886030184526131c7858351612f57565b945092850192908501906001016131ab565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156132645761325082865180516001600160a01b03168252602090810151910152565b93850193600193909301929082019061322a565b50979650505050505050565b6000806040838503121561328357600080fd5b823561328e81612c1c565b9150602083013561329e81612c1c565b809150509250929050565b6000806000606084860312156132be57600080fd5b83356132c981612c1c565b925060208401356132d981612c1c565b915060408401356132e981612c1c565b809150509250925092565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b848110156133bf57898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156133aa5761339683855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613370565b5050968901969450509187019160010161331c565b50919998505050505050505050565b6000806000604084860312156133e357600080fd5b83356001600160401b038111156133f957600080fd5b6134058682870161307b565b90945092505060208401356132e981612c1c565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561349b57613488838551613419565b9284019260c09290920191600101613475565b50909695505050505050565b81516001600160a01b0316815260208083015190820152604081016105aa565b61020081016105aa8284612e4e565b60c081016105aa8284613419565b6020808252825182820181905260009190848201906040850190845b8181101561349b5783516001600160a01b031683529284019291840191600101613500565b60006001600160401b0382111561353e5761353e612c44565b5060051b60200190565b6000602080838503121561355b57600080fd5b82356001600160401b0381111561357157600080fd5b8301601f8101851361358257600080fd5b8035613590612d8282613525565b81815260059190911b820183019083810190878311156135af57600080fd5b928401925b828410156135d65783356135c781612c1c565b825292840192908401906135b4565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561349b57613610838551612e4e565b9284019261020092909201916001016135fd565b6000602080838503121561363757600080fd5b82516001600160401b0381111561364d57600080fd5b8301601f8101851361365e57600080fd5b805161366c612d8282613525565b81815260059190911b8201830190838101908783111561368b57600080fd5b928401925b828410156135d65783516136a381612c1c565b82529284019290840190613690565b600082601f8301126136c357600080fd5b81516136d1612d8282612cd4565b8181528460208386010111156136e657600080fd5b610bb7826020830160208701612df2565b60006020828403121561370957600080fd5b81516001600160401b038082111561372057600080fd5b908301906060828603121561373457600080fd5b61373c612c82565b82518281111561374b57600080fd5b613757878286016136b2565b82525060208301518281111561376c57600080fd5b613778878286016136b2565b60208301525060408301518281111561379057600080fd5b61379c878286016136b2565b60408301525095945050505050565b6000602082840312156137bd57600080fd5b815161295581612c1c565b6000602082840312156137da57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161381f5761381f6137f7565b5060010190565b600060a0828403121561383857600080fd5b613840612c5a565b905081516001600160401b0381111561385857600080fd5b613864848285016136b2565b825250602082015161387581612c1c565b6020820152604082015161388881612c1c565b80604083015250606082015160608201526080820151608082015292915050565b600060208083850312156138bc57600080fd5b82516001600160401b03808211156138d357600080fd5b818501915085601f8301126138e757600080fd5b81516138f5612d8282613525565b81815260059190911b8301840190848101908883111561391457600080fd5b8585015b8381101561394c578051858111156139305760008081fd5b61393e8b89838a0101613826565b845250918601918601613918565b5098975050505050505050565b6000816000190483118215151615613973576139736137f7565b500290565b60008261399557634e487b7160e01b600052601260045260246000fd5b500490565b600082198211156139ad576139ad6137f7565b500190565b6000602082840312156139c457600080fd5b81516001600160401b038111156139da57600080fd5b610bb784828501613826565b600060208083850312156139f957600080fd5b82516001600160401b03811115613a0f57600080fd5b8301601f81018513613a2057600080fd5b8051613a2e612d8282613525565b81815260059190911b82018301908381019087831115613a4d57600080fd5b928401925b828410156135d6578351613a6581612c1c565b82529284019290840190613a52565b60008060408385031215613a8757600080fd5b82518015158114613a9757600080fd5b6020939093015192949293505050565b600060208284031215613ab957600080fd5b815160ff8116811461295557600080fd5b60006020808385031215613add57600080fd5b82516001600160401b03811115613af357600080fd5b8301601f81018513613b0457600080fd5b8051613b12612d8282613525565b81815260059190911b82018301908381019087831115613b3157600080fd5b928401925b828410156135d6578351613b4981612c1c565b82529284019290840190613b36565b80516001600160e01b0381168114612c3f57600080fd5b805163ffffffff81168114612c3f57600080fd5b600080600060608486031215613b9857600080fd5b613ba184613b58565b9250613baf60208501613b6f565b9150613bbd60408501613b6f565b90509250925092565b600060208284031215613bd857600080fd5b61295582613b58565b600082821015613bf357613bf36137f7565b500390565b6020815260006129556020830184612e2256fea2646970667358221220779aa170654683bfa5d56af49287aad0533e05083a4a11a6cf8812add9dcb69064736f6c634300080d0033", + "devdoc": { + "author": "Venus", + "kind": "dev", + "methods": { + "getAllPools(address)": { + "details": "This function is not designed to be called in a transaction: it is too gas-intensive", + "params": { + "poolRegistryAddress": "The address of the PoolRegistry contract" + }, + "returns": { + "_0": "Arrays of all Venus pools' data" + } + }, + "getPendingRewards(address,address)": { + "params": { + "account": "The user account.", + "comptrollerAddress": "address" + }, + "returns": { + "_0": "Pending rewards array" + } + }, + "getPoolBadDebt(address)": { + "params": { + "comptrollerAddress": "Address of the comptroller" + }, + "returns": { + "_0": "badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market" + } + }, + "getPoolByComptroller(address,address)": { + "params": { + "comptroller": "The Comptroller implementation address", + "poolRegistryAddress": "The address of the PoolRegistry contract" + }, + "returns": { + "_0": "PoolData structure containing the details of the pool" + } + }, + "getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))": { + "params": { + "poolRegistryAddress": "Address of the PoolRegistry", + "venusPool": "The VenusPool Object from PoolRegistry" + }, + "returns": { + "_0": "Enriched PoolData" + } + }, + "getPoolsSupportedByAsset(address,address)": { + "params": { + "asset": "The underlying asset of vToken", + "poolRegistryAddress": "The address of the PoolRegistry contract" + }, + "returns": { + "_0": "A list of Comptroller contracts" + } + }, + "getVTokenForAsset(address,address,address)": { + "params": { + "asset": "The underlyingAsset of VToken", + "comptroller": "The pool comptroller", + "poolRegistryAddress": "The address of the PoolRegistry contract" + }, + "returns": { + "_0": "Address of the vToken" + } + }, + "vTokenBalances(address,address)": { + "params": { + "account": "The user Account", + "vToken": "vToken address" + }, + "returns": { + "_0": "A struct containing the balances data" + } + }, + "vTokenBalancesAll(address[],address)": { + "params": { + "account": "The user Account", + "vTokens": "The list of vToken addresses" + }, + "returns": { + "_0": "A list of structs containing balances data" + } + }, + "vTokenMetadata(address)": { + "params": { + "vToken": "The address of vToken" + }, + "returns": { + "_0": "VTokenMetadata struct" + } + }, + "vTokenMetadataAll(address[])": { + "params": { + "vTokens": "The list of vToken addresses" + }, + "returns": { + "_0": "An array of VTokenMetadata structs" + } + }, + "vTokenUnderlyingPrice(address)": { + "params": { + "vToken": "vToken address" + }, + "returns": { + "_0": "The price data for each asset" + } + }, + "vTokenUnderlyingPriceAll(address[])": { + "params": { + "vTokens": "The list of vToken addresses" + }, + "returns": { + "_0": "An array containing the price data for each asset" + } + } + }, + "title": "PoolLens", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "getAllPools(address)": { + "notice": "Queries all pools with addtional details for each of them" + }, + "getPendingRewards(address,address)": { + "notice": "Returns the pending rewards for a user for a given pool." + }, + "getPoolBadDebt(address)": { + "notice": "Returns a summary of a pool's bad debt broken down by market" + }, + "getPoolByComptroller(address,address)": { + "notice": "Queries the details of a pool identified by Comptroller address" + }, + "getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))": { + "notice": "Queries additional information for the pool" + }, + "getPoolsSupportedByAsset(address,address)": { + "notice": "Returns all pools that support the specified underlying asset" + }, + "getVTokenForAsset(address,address,address)": { + "notice": "Returns vToken holding the specified underlying asset in the specified pool" + }, + "vTokenBalances(address,address)": { + "notice": "Queries the user's supply/borrow balances in the specified vToken" + }, + "vTokenBalancesAll(address[],address)": { + "notice": "Queries the user's supply/borrow balances in vTokens" + }, + "vTokenMetadata(address)": { + "notice": "Returns the metadata of VToken" + }, + "vTokenMetadataAll(address[])": { + "notice": "Returns the metadata of all VTokens" + }, + "vTokenUnderlyingPrice(address)": { + "notice": "Returns the price data for the underlying asset of the specified vToken" + }, + "vTokenUnderlyingPriceAll(address[])": { + "notice": "Returns the price data for the underlying assets of the specified vTokens" + } + }, + "notice": "The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/bscmainnet/ProtocolShareReserve.json b/deployments/sepolia/PoolRegistry.json similarity index 84% rename from deployments/bscmainnet/ProtocolShareReserve.json rename to deployments/sepolia/PoolRegistry.json index 0c1fdc6be..972ef0bdf 100644 --- a/deployments/bscmainnet/ProtocolShareReserve.json +++ b/deployments/sepolia/PoolRegistry.json @@ -1,5 +1,5 @@ { - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "abi": [ { "anonymous": false, @@ -125,33 +125,42 @@ "type": "receive" }, { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "sender", "type": "address" }, { - "indexed": true, "internalType": "address", - "name": "asset", + "name": "calledContract", "type": "address" }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ { "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "name": "AssetsReservesUpdated", + "name": "Initialized", "type": "event" }, { @@ -166,17 +175,11 @@ { "indexed": true, "internalType": "address", - "name": "asset", + "name": "vTokenAddress", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "FundsReleased", + "name": "MarketAdded", "type": "event" }, { @@ -184,12 +187,18 @@ "inputs": [ { "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" } ], - "name": "Initialized", + "name": "NewAccessControlManager", "type": "event" }, { @@ -236,17 +245,57 @@ { "indexed": true, "internalType": "address", - "name": "oldPoolRegistry", + "name": "comptroller", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newPoolRegistry", - "type": "address" + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "oldMetadata", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "newMetadata", + "type": "tuple" } ], - "name": "PoolRegistryUpdated", + "name": "PoolMetadataUpdated", "type": "event" }, { @@ -255,23 +304,69 @@ { "indexed": true, "internalType": "address", - "name": "token", + "name": "comptroller", "type": "address" }, + { + "indexed": false, + "internalType": "string", + "name": "oldName", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newName", + "type": "string" + } + ], + "name": "PoolNameSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, "internalType": "address", - "name": "to", + "name": "comptroller", "type": "address" }, { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "pool", + "type": "tuple" } ], - "name": "SweepToken", + "name": "PoolRegistered", "type": "event" }, { @@ -282,21 +377,144 @@ "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "accessControlManager", + "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } ], - "name": "assetsReserves", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSupply", + "type": "uint256" + }, + { + "internalType": "address", + "name": "vTokenReceiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplyCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistry.AddMarketInput", + "name": "input", + "type": "tuple" + } + ], + "name": "addMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "contract Comptroller", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "addPool", "outputs": [ { "internalType": "uint256", - "name": "", + "name": "index", "type": "uint256" } ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllPools", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool[]", + "name": "", + "type": "tuple[]" + } + ], "stateMutability": "view", "type": "function" }, @@ -306,19 +524,60 @@ "internalType": "address", "name": "comptroller", "type": "address" - }, + } + ], + "name": "getPoolByComptroller", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", "name": "asset", "type": "address" } ], - "name": "getPoolAssetReserve", + "name": "getPoolsSupportedByAsset", "outputs": [ { - "internalType": "uint256", + "internalType": "address[]", "name": "", - "type": "uint256" + "type": "address[]" } ], "stateMutability": "view", @@ -328,23 +587,16 @@ "inputs": [ { "internalType": "address", - "name": "protocolIncome_", + "name": "comptroller", "type": "address" }, { "internalType": "address", - "name": "riskFund_", + "name": "asset", "type": "address" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", + "name": "getVTokenForAsset", "outputs": [ { "internalType": "address", @@ -356,83 +608,99 @@ "type": "function" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "comptroller", "type": "address" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "poolRegistry", + "name": "getVenusPoolMetadata", "outputs": [ { - "internalType": "address", + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", "name": "", - "type": "address" + "type": "tuple" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "protocolIncome", - "outputs": [ + "inputs": [ { "internalType": "address", - "name": "", + "name": "accessControlManager_", "type": "address" } ], - "stateMutability": "view", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" + } + ], + "name": "metadata", + "outputs": [ + { + "internalType": "string", + "name": "category", + "type": "string" }, { - "internalType": "address", - "name": "asset", - "type": "address" + "internalType": "string", + "name": "logoURL", + "type": "string" }, { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "string", + "name": "description", + "type": "string" } ], - "name": "releaseFunds", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "riskFund", + "name": "pendingOwner", "outputs": [ { "internalType": "address", @@ -443,15 +711,22 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { "internalType": "address", - "name": "poolRegistry_", + "name": "accessControlManager_", "type": "address" } ], - "name": "setPoolRegistry", + "name": "setAccessControlManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -460,16 +735,16 @@ "inputs": [ { "internalType": "address", - "name": "_token", + "name": "comptroller", "type": "address" }, { - "internalType": "address", - "name": "_to", - "type": "address" + "internalType": "string", + "name": "name", + "type": "string" } ], - "name": "sweepToken", + "name": "setPoolName", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -495,12 +770,29 @@ "type": "address" }, { - "internalType": "address", - "name": "asset", - "type": "address" - } - ], - "name": "updateAssetsState", + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "metadata_", + "type": "tuple" + } + ], + "name": "updatePoolMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -527,74 +819,84 @@ "type": "constructor" } ], - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", "receipt": { "to": null, - "from": "0x55A9f5374Af30E3045FB491f1da3C2E8a74d168D", - "contractAddress": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", - "transactionIndex": 111, - "gasUsed": "817682", - "logsBloom": "0x00000000010000000000000000000000400000000000000000800000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000002000001000000000000000000000000000000010000020000000000000000000800000000800000000000000000000000400001800000080000000000000000000000000000000080000000000000800000000000000000000000000000000400000000000000000000000000000002000000000020000000000000000000040000000000000400000000000000001020000000000000000000000000000000000000000000000000000000000000000100", - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112", - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x758f5715d817e02857Ba40889251201A5aE3E186", + "transactionIndex": 53, + "gasUsed": "796718", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000000000000000000000000000200000000000000008000000010000000000000000000000002000001000000000000002000000000000000080000020000000000000000000800000000800000000000000000000000400000000000000000000800000000000000000000000080000000000000800000000000000000000000000000000400000000000000800000000400000000000000000020000000000000000110040000000000000400000000000000000020000000020000000000000000000000000000000800000000000000000000000000", + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746", + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", "logs": [ { - "transactionIndex": 111, - "blockNumber": 31670925, - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", - "0x000000000000000000000000c1c56732fcafca0f66d59745ec69dc642ec20ab8" + "0x0000000000000000000000003213607db41319e32c3706116adf1ae890e4083a" ], "data": "0x", - "logIndex": 258, - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112" + "logIndex": 53, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" }, { - "transactionIndex": 111, - "blockNumber": 31670925, - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000055a9f5374af30e3045fb491f1da3c2e8a74d168d" + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" ], "data": "0x", - "logIndex": 259, - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112" + "logIndex": 54, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" + }, + { + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 55, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" }, { - "transactionIndex": 111, - "blockNumber": 31670925, - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 260, - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112" + "logIndex": 56, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" }, { - "transactionIndex": 111, - "blockNumber": 31670925, - "transactionHash": "0x47ddbdb20be15cd6c7ec5090c11a9fdf035b23ce0689b18e42141003f4ce9d9c", - "address": "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006beb6d2695b67feb73ad4f172e8e2975497187e4", - "logIndex": 261, - "blockHash": "0xa320e6f5001fdfe6e5a63cf1f4a8da72f57bcc0a2fab4f5903dc095ba8a9e112" + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e98a3110929c6650c73031756288ec518f65e846", + "logIndex": 57, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" } ], - "blockNumber": 31670925, - "cumulativeGasUsed": "13118645", + "blockNumber": 4776616, + "cumulativeGasUsed": "10451599", "status": 1, "byzantium": true }, "args": [ - "0xc1c56732FcaFca0F66D59745Ec69DC642EC20ab8", - "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", - "0x485cc955000000000000000000000000f322942f644a996a617bd29c16bd7d231d9f35e9000000000000000000000000df31a28d68a2ab381d42b380649ead7ae2a76e42" + "0x3213607Db41319E32C3706116Adf1Ae890E4083A", + "0xe98a3110929c6650c73031756288Ec518f65e846", + "0xc4d66de8000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96" ], "numDeployments": 1, "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", @@ -603,9 +905,9 @@ "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", "execute": { "methodName": "initialize", - "args": ["0xF322942f644A996A617BD29c16bd7d231d9F35E9", "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42"] + "args": ["0xbf705C00578d43B6147ab4eaE04DBBEd1ccCdc96"] }, - "implementation": "0xc1c56732FcaFca0F66D59745Ec69DC642EC20ab8", + "implementation": "0x3213607Db41319E32C3706116Adf1Ae890E4083A", "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", diff --git a/deployments/sepolia/PoolRegistry_Implementation.json b/deployments/sepolia/PoolRegistry_Implementation.json new file mode 100644 index 000000000..65ffda497 --- /dev/null +++ b/deployments/sepolia/PoolRegistry_Implementation.json @@ -0,0 +1,1189 @@ +{ + "address": "0x3213607Db41319E32C3706116Adf1Ae890E4083A", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "MarketAdded", + "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" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "oldMetadata", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "newMetadata", + "type": "tuple" + } + ], + "name": "PoolMetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "oldName", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newName", + "type": "string" + } + ], + "name": "PoolNameSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "pool", + "type": "tuple" + } + ], + "name": "PoolRegistered", + "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": [ + { + "components": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSupply", + "type": "uint256" + }, + { + "internalType": "address", + "name": "vTokenReceiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplyCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistry.AddMarketInput", + "name": "input", + "type": "tuple" + } + ], + "name": "addMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "contract Comptroller", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "addPool", + "outputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllPools", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolByComptroller", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPoolsSupportedByAsset", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getVTokenForAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getVenusPoolMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "metadata", + "outputs": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "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": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "setPoolName", + "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" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "metadata_", + "type": "tuple" + } + ], + "name": "updatePoolMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x88002b38665795a0b712e5a23ea55f3d60510d53b5fee3d472ec60f84b691e18", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x3213607Db41319E32C3706116Adf1Ae890E4083A", + "transactionIndex": 73, + "gasUsed": "2602796", + "logsBloom": "0x00000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000002000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x713de2e81c558b28f101cfc9c843737b6021a5fa8b436615e5f1807706d86236", + "transactionHash": "0x88002b38665795a0b712e5a23ea55f3d60510d53b5fee3d472ec60f84b691e18", + "logs": [ + { + "transactionIndex": 73, + "blockNumber": 4776615, + "transactionHash": "0x88002b38665795a0b712e5a23ea55f3d60510d53b5fee3d472ec60f84b691e18", + "address": "0x3213607Db41319E32C3706116Adf1Ae890E4083A", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", + "logIndex": 63, + "blockHash": "0x713de2e81c558b28f101cfc9c843737b6021a5fa8b436615e5f1807706d86236" + } + ], + "blockNumber": 4776615, + "cumulativeGasUsed": "11209256", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"}],\"name\":\"MarketAdded\",\"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\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"indexed\":false,\"internalType\":\"struct PoolRegistryInterface.VenusPoolMetaData\",\"name\":\"oldMetadata\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"indexed\":false,\"internalType\":\"struct PoolRegistryInterface.VenusPoolMetaData\",\"name\":\"newMetadata\",\"type\":\"tuple\"}],\"name\":\"PoolMetadataUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"oldName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"newName\",\"type\":\"string\"}],\"name\":\"PoolNameSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"pool\",\"type\":\"tuple\"}],\"name\":\"PoolRegistered\",\"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\":[{\"components\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThreshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialSupply\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"vTokenReceiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"supplyCap\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCap\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistry.AddMarketInput\",\"name\":\"input\",\"type\":\"tuple\"}],\"name\":\"addMarket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"contract Comptroller\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"}],\"name\":\"addPool\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getVenusPoolMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPoolMetaData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"metadata\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setPoolName\",\"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\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPoolMetaData\",\"name\":\"metadata_\",\"type\":\"tuple\"}],\"name\":\"updatePoolMetadata\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"addMarket((address,uint256,uint256,uint256,address,uint256,uint256))\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when vToken address is zeroZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\",\"params\":{\"input\":\"The structure describing the parameters for adding a market to a pool\"}},\"addPool(string,address,uint256,uint256,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when Comptroller address is zeroZeroAddressNotAllowed is thrown when price oracle address is zero\",\"details\":\"Price oracle must be configured before adding a pool\",\"params\":{\"closeFactor\":\"The pool's close factor (scaled by 1e18)\",\"comptroller\":\"Pool's Comptroller contract\",\"liquidationIncentive\":\"The pool's liquidation incentive (scaled by 1e18)\",\"minLiquidatableCollateral\":\"Minimal collateral for regular (non-batch) liquidations flow\",\"name\":\"The name of the pool\"},\"returns\":{\"index\":\"The index of the registered Venus pool\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"getAllPools()\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"returns\":{\"_0\":\"A list of all pools within PoolRegistry, with details for each pool\"}},\"getPoolByComptroller(address)\":{\"params\":{\"comptroller\":\"The comptroller proxy address associated to the pool\"},\"returns\":{\"_0\":\"Returns Venus pool\"}},\"getVenusPoolMetadata(address)\":{\"params\":{\"comptroller\":\"comptroller of Venus pool\"},\"returns\":{\"_0\":\"Returns Metadata of Venus pool\"}},\"initialize(address)\":{\"params\":{\"accessControlManager_\":\"AccessControlManager contract address\"}},\"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\"}},\"setPoolName(address,string)\":{\"params\":{\"comptroller\":\"Pool's Comptroller\",\"name\":\"New pool name\"}},\"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.\"},\"updatePoolMetadata(address,(string,string,string))\":{\"params\":{\"comptroller\":\"Pool's Comptroller\",\"metadata_\":\"New pool metadata\"}}},\"stateVariables\":{\"_numberOfPools\":{\"details\":\"Total number of pools created.\"},\"_poolByComptroller\":{\"details\":\"Maps comptroller address to Venus pool Index.\"},\"_poolsByID\":{\"details\":\"Maps pool ID to pool's comptroller address\"},\"_supportedPools\":{\"details\":\"Maps asset to list of supported pools.\"},\"_vTokens\":{\"details\":\"Maps pool's comptroller address to asset to vToken.\"}},\"title\":\"PoolRegistry\",\"version\":1},\"userdoc\":{\"errors\":{\"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\":{\"MarketAdded(address,address)\":{\"notice\":\"Emitted when a Market is added to the pool.\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PoolMetadataUpdated(address,(string,string,string),(string,string,string))\":{\"notice\":\"Emitted when a pool metadata is updated.\"},\"PoolNameSet(address,string,string)\":{\"notice\":\"Emitted when a pool name is set.\"},\"PoolRegistered(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Emitted when a new Venus pool is added to the directory.\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"addMarket((address,uint256,uint256,uint256,address,uint256,uint256))\":{\"notice\":\"Add a market to an existing pool and then mint to provide initial supply\"},\"addPool(string,address,uint256,uint256,uint256)\":{\"notice\":\"Adds a new Venus pool to the directory\"},\"getAllPools()\":{\"notice\":\"Returns arrays of all Venus pools' data\"},\"getPoolsSupportedByAsset(address)\":{\"notice\":\"Get the addresss of the Pools supported that include a market for the provided asset\"},\"getVTokenForAsset(address,address)\":{\"notice\":\"Get the address of the VToken contract in the Pool where the underlying token is the provided asset\"},\"initialize(address)\":{\"notice\":\"Initializes the deployer to owner\"},\"metadata(address)\":{\"notice\":\"Maps pool's comptroller address to metadata.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setPoolName(address,string)\":{\"notice\":\"Modify existing Venus pool name\"},\"updatePoolMetadata(address,(string,string,string))\":{\"notice\":\"Update metadata of an existing pool\"}},\"notice\":\"The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required metadata, and providing the getter methods to get information on the pools. Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools. It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`) and setting pool name (`setPoolName`). The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's comptroller address. `_poolsByID` is used to iterate through all of the pools. PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by asset is retrieved by calling `getPoolsSupportedByAsset`. PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with specific assets and custom risk management configurations according to their markets.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Pool/PoolRegistry.sol\":\"PoolRegistry\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"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/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.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"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/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/protocol-reserve/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/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor is changed by admin\\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow.\\n * @param vTokenAddress The address of the asset to be removed\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return NO_ERROR;\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\n _checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = accountAssets[user];\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = accountAssets[borrower];\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n _ensureMaxLoops(numMarkets);\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Enables forced liquidations for a market. If forced liquidation is enabled,\\n * borrows in the market may be liquidated regardless of the account liquidity\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall Hypothetical account shortfall below collateral requirements\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Check if a market is marked as listed (active)\\n * @param vToken vToken Address for the market to check\\n * @return listed True if listed otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].isListed;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n VToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the market specified, otherwise false.\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = accountAssets[account];\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n }\\n\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = accountAssets[account];\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x42f9cceba5f1b4d82047f930a7049740d13ab36004bb1a58b462b9e111c08665\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x44c67531518072db11bf6eafe29499073724346a7855579b09a9da049742d879\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // Multiplier representing the most one can borrow against their collateral in this market.\\n // For instance, 0.9 to allow borrowing 90% of collateral value.\\n // Must be between 0 and 1, and stored as a mantissa.\\n uint256 collateralFactorMantissa;\\n // Multiplier representing the collateralization after which the borrow is eligible\\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n // value. Must be between 0 and collateral factor, stored as a mantissa.\\n uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\n enum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n }\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint256 public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n /**\\n * @notice Official mapping of vTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\\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\":\"0xdfc033911c20e09516110ae3f94740b4be1a065baee4412a708e25a25568eac8\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x3f8ec4e18bca1fdf8619966f4f6e095e205517a78f8c741b87fe82125754f96f\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x1f17b8e3fdd89657d488250140f6d6abeb04f2b822467139687487f9c1dbe397\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"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\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\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\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\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 /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.approve(vTokenAddress, 0);\\n underlying.approve(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0x425c5d620fab58b88132a2b00a5d20789fae4f79bd7795d00861be7b3625d4dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title PoolRegistryInterface\\n * @author Venus\\n * @notice Interface implemented by `PoolRegistry`.\\n */\\ninterface PoolRegistryInterface {\\n /**\\n * @notice Struct for a Venus interest rate pool.\\n */\\n struct VenusPool {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n }\\n\\n /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7e8ccd190ef019a3f8c3fcb67ed3eadd7bed32b263f88566870d138cd95ae312\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each block for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller private comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlock(address[],uint32[],uint32[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumber();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\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 */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumber = getBlockNumber();\\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n function getBlockNumber() public view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumber();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplyIndex = supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowIndex = borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\\n blockNumber = supplyState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\\n\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n supplyState.index = safe224(\\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n supplyState.block = blockNumber;\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\\n blockNumber = borrowState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n borrowState.index = safe224(\\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n borrowState.block = blockNumber;\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0x598aad1a12d6a895f82a8b619000099efe53994fe89522b41adaa68819fac652\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n /**\\n * Reentrancy Guard **\\n */\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\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 /**\\n * @notice Construct a new money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\n );\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n _borrowFresh(msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == _getBlockNumber()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockDelta block difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockDelta;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return amount The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return rate The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this v\\n * @return rate The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number */\\n uint256 currentBlockNumber = _getBlockNumber();\\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentBlockNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n _reduceReservesFresh(totalReservesNew);\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is sending the assets for supply\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `_doTransferIn` for the minter and the mintAmount.\\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n }\\n\\n /**\\n * @notice User redeems vTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n */\\n function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\\n * On success, the vToken has redeemAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(redeemer, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrower User who borrows the assets\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the borrower and the borrowAmount.\\n * On success, the vToken borrowAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(borrower, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call _doTransferIn for the payer and the repayAmount\\n * On success, the vToken holds an additional repayAmount of cash.\\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == NO_ERROR, \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetInterestRateModelFreshCheck();\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n }\\n\\n /**\\n * Safe Token **\\n */\\n\\n /**\\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\\n * This function returns the actual amount received,\\n * which may be less than `amount` if there is a fee attached to the transfer.\\n * @param from Sender of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n * @return Actual amount received\\n */\\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n // Return the amount that was *actually* transferred\\n return balanceAfter - balanceBefore;\\n }\\n\\n /**\\n * @dev Just a regular ERC-20 transfer, reverts on failure\\n * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n _setComptroller(comptroller_);\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = _getBlockNumber();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying tokens owned by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n * @return Current block number\\n */\\n function _getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xf4f49f4a1718a36a7cbd413e959d957eade62d4ad96c0ebde4562e53cac72f7e\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\n\\n // Maximum borrow rate that can ever be applied (.0005% / block)\\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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[48] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves block delta is changed\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x777842977e2441dd79f4781ff61f431dda351c3d33862e40063ef58d03b489a1\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x909eb76841ebd57d8f53686b76b1a09da7bbbbcddb29510c41674d5aa84c713e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b612da080620000f36000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c8063a3aefa2c116100a2578063e30c397811610071578063e30c397814610267578063eed873c214610278578063f2fde38b14610299578063f36dba38146102ac578063ff94d958146102cc57600080fd5b8063a3aefa2c1461020e578063b4a0bdf31461022e578063c4d66de81461023f578063d88ff1f41461025257600080fd5b80632ba21572116100e95780632ba21572146101ab578063715018a6146101cd57806379ba5097146101d55780637aee632d146101dd5780638da5cb5b146101fd57600080fd5b80630e32cb861461011b5780631cb6bb7e1461013057806323dc8d6414610143578063266e0a7f14610156575b600080fd5b61012e6101293660046122f1565b6102df565b005b61012e61013e36600461235e565b6102f3565b61012e6101513660046123c9565b610440565b61018e610164366004612459565b6001600160a01b03918216600090815260cd60209081526040808320938516835292905220541690565b6040516001600160a01b0390911681526020015b60405180910390f35b6101be6101b93660046122f1565b610b96565b6040516101a2939291906124ea565b61012e610d50565b61012e610d64565b6101f06101eb3660046122f1565b610ddb565b6040516101a2919061257a565b6033546001600160a01b031661018e565b61022161021c3660046122f1565b610ed2565b6040516101a291906125de565b6097546001600160a01b031661018e565b61012e61024d3660046122f1565b6110d5565b61025a6111f1565b6040516101a291906125f1565b6065546001600160a01b031661018e565b61028b610286366004612653565b611392565b6040519081526020016101a2565b61012e6102a73660046122f1565b611552565b6102bf6102ba3660046122f1565b6115c3565b6040516101a291906126c4565b61012e6102da366004612711565b611639565b6102e76118a4565b6102f0816118fe565b50565b6103316040518060400160405280601b81526020017f736574506f6f6c4e616d6528616464726573732c737472696e672900000000008152506119bc565b61033b8282611a56565b6001600160a01b038316600090815260cc60205260408120805490919082906103639061275d565b80601f016020809104026020016040519081016040528092919081815260200182805461038f9061275d565b80156103dc5780601f106103b1576101008083540402835291602001916103dc565b820191906000526020600020905b8154815290600101906020018083116103bf57829003601f168201915b509394506103f3935085925087915086905061217e565b50846001600160a01b03167fa01f2b0df2b143bfb23d4b696c103547a6bec8ca1f56e8e8a483611cb4e23a7e828686604051610431939291906127c0565b60405180910390a25050505050565b61047e6040518060400160405280601981526020017f6164644d61726b6574284164644d61726b6574496e70757429000000000000008152506119bc565b805161048990611aa7565b6104968160800151611aa7565b60008160600151116104fb5760405162461bcd60e51b815260206004820152602360248201527f506f6f6c52656769737472793a20696e697469616c537570706c79206973207a60448201526265726f60e81b60648201526084015b60405180910390fd5b60008160000151905060008190506000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056d91906127e6565b905060008190506000846001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d891906127e6565b6001600160a01b03848116600090815260cc60205260409020600101549192508291166106515760405162461bcd60e51b815260206004820152602160248201527f506f6f6c52656769737472793a20506f6f6c206e6f74207265676973746572656044820152601960fa1b60648201526084016104f2565b6001600160a01b03848116600090815260cd60209081526040808320868516845290915290205416156106fa5760405162461bcd60e51b8152602060048201526044602482018190527f506f6f6c52656769737472793a204d61726b657420616c726561647920616464908201527f656420666f7220617373657420636f6d7074726f6c6c657220636f6d62696e616064820152633a34b7b760e11b608482015260a4016104f2565b6040516332ad3e1360e21b81526001600160a01b03878116600483015284169063cab4f84c90602401600060405180830381600087803b15801561073d57600080fd5b505af1158015610751573d6000803e3d6000fd5b5050505060208701516040808901519051635cc4fdeb60e01b81526001600160a01b0389811660048301526024820193909352604481019190915290841690635cc4fdeb90606401600060405180830381600087803b1580156107b357600080fd5b505af11580156107c7573d6000803e3d6000fd5b5060009250600191506107d79050565b604051908082528060200260200182016040528015610800578160200160208202803683370190505b50604080516001808252818301909252919250600091906020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508960a001518360008151811061086257610862612803565b6020026020010181815250508960c001518260008151811061088657610886612803565b60200260200101818152505088816000815181106108a6576108a6612803565b6001600160a01b03928316602091820292909201015260405163344dabd160e21b81529087169063d136af44906108e39084908790600401612819565b600060405180830381600087803b1580156108fd57600080fd5b505af1158015610911573d6000803e3d6000fd5b505060405163186db48f60e01b81526001600160a01b038916925063186db48f91506109439084908690600401612819565b600060405180830381600087803b15801561095d57600080fd5b505af1158015610971573d6000803e3d6000fd5b5050506001600160a01b03808916600081815260cd602090815260408083208b8616845282528083208054958f166001600160a01b031996871617905560ce82528220805460018101825590835290822001805490931690911790915560608c01519091506109e39086903390611ace565b60405163095ea7b360e01b81526001600160a01b038b81166004830152600060248301529192509086169063095ea7b3906044016020604051808303816000875af1158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5a919061289d565b5060405163095ea7b360e01b81526001600160a01b038a811660048301526024820183905286169063095ea7b3906044016020604051808303816000875af1158015610aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ace919061289d565b5060808b01516040516323323e0360e01b81526001600160a01b03918216600482015260248101839052908b16906323323e03906044016020604051808303816000875af1158015610b24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4891906128bf565b50886001600160a01b0316886001600160a01b03167f7772c85e68debdf74fad87834e2cc05fa763e74faf14de7096da30529065114260405160405180910390a35050505050505050505050565b60c960205260009081526040902080548190610bb19061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdd9061275d565b8015610c2a5780601f10610bff57610100808354040283529160200191610c2a565b820191906000526020600020905b815481529060010190602001808311610c0d57829003601f168201915b505050505090806001018054610c3f9061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6b9061275d565b8015610cb85780601f10610c8d57610100808354040283529160200191610cb8565b820191906000526020600020905b815481529060010190602001808311610c9b57829003601f168201915b505050505090806002018054610ccd9061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610cf99061275d565b8015610d465780601f10610d1b57610100808354040283529160200191610d46565b820191906000526020600020905b815481529060010190602001808311610d2957829003601f168201915b5050505050905083565b610d586118a4565b610d626000611bd3565b565b60655433906001600160a01b03168114610dd25760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016104f2565b6102f081611bd3565b610de3612202565b6001600160a01b038216600090815260cc602052604090819020815160a08101909252805482908290610e159061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610e419061275d565b8015610e8e5780601f10610e6357610100808354040283529160200191610e8e565b820191906000526020600020905b815481529060010190602001808311610e7157829003601f168201915b505050918352505060018201546001600160a01b03908116602083015260028301541660408201526003820154606082015260049091015460809091015292915050565b610ef660405180606001604052806060815260200160608152602001606081525090565b6001600160a01b038216600090815260c9602052604090819020815160608101909252805482908290610f289061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f549061275d565b8015610fa15780601f10610f7657610100808354040283529160200191610fa1565b820191906000526020600020905b815481529060010190602001808311610f8457829003601f168201915b50505050508152602001600182018054610fba9061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610fe69061275d565b80156110335780601f1061100857610100808354040283529160200191611033565b820191906000526020600020905b81548152906001019060200180831161101657829003601f168201915b5050505050815260200160028201805461104c9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546110789061275d565b80156110c55780601f1061109a576101008083540402835291602001916110c5565b820191906000526020600020905b8154815290600101906020018083116110a857829003601f168201915b5050505050815250509050919050565b600054610100900460ff16158080156110f55750600054600160ff909116105b8061110f5750303b15801561110f575060005460ff166001145b6111725760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016104f2565b6000805460ff191660011790558015611195576000805461ff0019166101001790555b61119d611bec565b6111a682611c1b565b80156111ed576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a15b5050565b60cb5460609060008167ffffffffffffffff811115611212576112126123b3565b60405190808252806020026020018201604052801561124b57816020015b611238612202565b8152602001906001900390816112305790505b50905060015b82811161138b57600081815260ca60209081526040808320546001600160a01b031680845260cc90925291829020825160a0810190935280549192918290829061129a9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546112c69061275d565b80156113135780601f106112e857610100808354040283529160200191611313565b820191906000526020600020905b8154815290600101906020018083116112f657829003601f168201915b50505091835250506001828101546001600160a01b039081166020840152600284015416604083015260038301546060830152600490920154608090910152849061135e90856128ee565b8151811061136e5761136e612803565b6020026020010181905250508061138490612905565b9050611251565b5092915050565b60006113b56040518060600160405280602f8152602001612d3c602f91396119bc565b6113be85611aa7565b611428856001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142391906127e6565b611aa7565b6000611435888888611c42565b60405163091a474b60e11b8152600481018790529091506001600160a01b038716906312348e9690602401600060405180830381600087803b15801561147a57600080fd5b505af115801561148e573d6000803e3d6000fd5b505060405163a843108160e01b8152600481018790526001600160a01b038916925063a84310819150602401600060405180830381600087803b1580156114d457600080fd5b505af11580156114e8573d6000803e3d6000fd5b5050604051631482db1d60e21b8152600481018690526001600160a01b038916925063520b6c749150602401600060405180830381600087803b15801561152e57600080fd5b505af1158015611542573d6000803e3d6000fd5b50929a9950505050505050505050565b61155a6118a4565b606580546001600160a01b0383166001600160a01b0319909116811790915561158b6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6001600160a01b038116600090815260ce602090815260409182902080548351818402810184019094528084526060939283018282801561162d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161160f575b50505050509050919050565b61165a6040518060600160405280602d8152602001612d0f602d91396119bc565b6001600160a01b038216600090815260c9602052604080822081516060810190925280548290829061168b9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546116b79061275d565b80156117045780601f106116d957610100808354040283529160200191611704565b820191906000526020600020905b8154815290600101906020018083116116e757829003601f168201915b5050505050815260200160018201805461171d9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546117499061275d565b80156117965780601f1061176b57610100808354040283529160200191611796565b820191906000526020600020905b81548152906001019060200180831161177957829003601f168201915b505050505081526020016002820180546117af9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546117db9061275d565b80156118285780601f106117fd57610100808354040283529160200191611828565b820191906000526020600020905b81548152906001019060200180831161180b57829003601f168201915b505050919092525050506001600160a01b038416600090815260c96020526040902090915082906118598282612a74565b905050826001600160a01b03167f8f91f3b5d20b61744ed591c43346d4514ee5c2ffced5fc3795bb13c6f95181478284604051611897929190612bba565b60405180910390a2505050565b6033546001600160a01b03163314610d625760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f2565b6001600160a01b0381166119625760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b60648201526084016104f2565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e4565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906119ef9033908690600401612c44565b602060405180830381865afa158015611a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a30919061289d565b9050806111ed57333083604051634a3fa29360e01b81526004016104f293929190612c68565b60648111156111ed5760405162461bcd60e51b815260206004820152601860248201527f506f6f6c2773206e616d6520697320746f6f206c61726765000000000000000060448201526064016104f2565b6001600160a01b0381166102f0576040516342bcdf7f60e11b815260040160405180910390fd5b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a0823190602401602060405180830381865afa158015611b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3b91906128bf565b9050611b526001600160a01b038616853086611e32565b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015611b99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbd91906128bf565b9050611bc982826128ee565b9695505050505050565b606580546001600160a01b03191690556102f081611e92565b600054610100900460ff16611c135760405162461bcd60e51b81526004016104f290612c94565b610d62611ee4565b600054610100900460ff166102e75760405162461bcd60e51b81526004016104f290612c94565b6001600160a01b03808216600090815260cc602052604081206001810154919290911615611cce5760405162461bcd60e51b815260206004820152603360248201527f506f6f6c52656769737472793a20506f6f6c20616c7265616479206578697374604482015272399034b7103a3432903234b932b1ba37b93c9760691b60648201526084016104f2565b611cd88585611a56565b60cb60008154611ce790612905565b9091555060cb546040805160c06020601f8901819004028201810190925260a081018781526000928291908a908a908190850183828082843760009201829052509385525050336020808501919091526001600160a01b038a1660408086018290524360608701524260809096019590955287845260ca825284842080546001600160a01b03191682179055835260cc8152929091208351805194955085949193611d9793508492910190612243565b5060208201516001820180546001600160a01b03199081166001600160a01b039384161790915560408085015160028501805490931690841617909155606084015160038401556080909301516004909201919091559051908616907f53ec2a1d9645c4631472dabcf6d255f5f2971baa64321235b1610d91c692928e90611e2090849061257a565b60405180910390a25095945050505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611e8c908590611f14565b50505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611f0b5760405162461bcd60e51b81526004016104f290612c94565b610d6233611bd3565b6000611f69826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611fee9092919063ffffffff16565b9050805160001480611f8a575080806020019051810190611f8a919061289d565b611fe95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104f2565b505050565b6060611ffd8484600085612005565b949350505050565b6060824710156120665760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016104f2565b600080866001600160a01b031685876040516120829190612cdf565b60006040518083038185875af1925050503d80600081146120bf576040519150601f19603f3d011682016040523d82523d6000602084013e6120c4565b606091505b50915091506120d5878383876120e0565b979650505050505050565b6060831561214f578251600003612148576001600160a01b0385163b6121485760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104f2565b5081611ffd565b611ffd83838151156121645781518083602001fd5b8060405162461bcd60e51b81526004016104f29190612cfb565b82805461218a9061275d565b90600052602060002090601f0160209004810192826121ac57600085556121f2565b82601f106121c55782800160ff198235161785556121f2565b828001600101855582156121f2579182015b828111156121f25782358255916020019190600101906121d7565b506121fe9291506122b7565b5090565b6040518060a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081525090565b82805461224f9061275d565b90600052602060002090601f01602090048101928261227157600085556121f2565b82601f1061228a57805160ff19168380011785556121f2565b828001600101855582156121f2579182015b828111156121f257825182559160200191906001019061229c565b5b808211156121fe57600081556001016122b8565b6001600160a01b03811681146102f057600080fd5b80356122ec816122cc565b919050565b60006020828403121561230357600080fd5b813561230e816122cc565b9392505050565b60008083601f84011261232757600080fd5b50813567ffffffffffffffff81111561233f57600080fd5b60208301915083602082850101111561235757600080fd5b9250929050565b60008060006040848603121561237357600080fd5b833561237e816122cc565b9250602084013567ffffffffffffffff81111561239a57600080fd5b6123a686828701612315565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b600060e082840312156123db57600080fd5b60405160e0810181811067ffffffffffffffff821117156123fe576123fe6123b3565b60405261240a836122e1565b8152602083013560208201526040830135604082015260608301356060820152612436608084016122e1565b608082015260a083013560a082015260c083013560c08201528091505092915050565b6000806040838503121561246c57600080fd5b8235612477816122cc565b91506020830135612487816122cc565b809150509250929050565b60005b838110156124ad578181015183820152602001612495565b83811115611e8c5750506000910152565b600081518084526124d6816020860160208601612492565b601f01601f19169290920160200192915050565b6060815260006124fd60608301866124be565b828103602084015261250f81866124be565b90508281036040840152611bc981856124be565b6000815160a0845261253860a08501826124be565b9050602083015160018060a01b038082166020870152806040860151166040870152505060608301516060850152608083015160808501528091505092915050565b60208152600061230e6020830184612523565b60008151606084526125a260608501826124be565b9050602083015184820360208601526125bb82826124be565b915050604083015184820360408601526125d582826124be565b95945050505050565b60208152600061230e602083018461258d565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561264657603f19888603018452612634858351612523565b94509285019290850190600101612618565b5092979650505050505050565b60008060008060008060a0878903121561266c57600080fd5b863567ffffffffffffffff81111561268357600080fd5b61268f89828a01612315565b90975095505060208701356126a3816122cc565b95989497509495604081013595506060810135946080909101359350915050565b6020808252825182820181905260009190848201906040850190845b818110156127055783516001600160a01b0316835292840192918401916001016126e0565b50909695505050505050565b6000806040838503121561272457600080fd5b823561272f816122cc565b9150602083013567ffffffffffffffff81111561274b57600080fd5b83016060818603121561248757600080fd5b600181811c9082168061277157607f821691505b60208210810361279157634e487b7160e01b600052602260045260246000fd5b50919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040815260006127d360408301866124be565b8281036020840152611bc9818587612797565b6000602082840312156127f857600080fd5b815161230e816122cc565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b8281101561285b5781516001600160a01b031684529284019290840190600101612836565b5050508381038285015284518082528583019183019060005b8181101561289057835183529284019291840191600101612874565b5090979650505050505050565b6000602082840312156128af57600080fd5b8151801515811461230e57600080fd5b6000602082840312156128d157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612900576129006128d8565b500390565b600060018201612917576129176128d8565b5060010190565b6000808335601e1984360301811261293557600080fd5b83018035915067ffffffffffffffff82111561295057600080fd5b60200191503681900382131561235757600080fd5b601f821115611fe957600081815260208120601f850160051c8101602086101561298c5750805b601f850160051c820191505b818110156129ab57828155600101612998565b505050505050565b67ffffffffffffffff8311156129cb576129cb6123b3565b6129df836129d9835461275d565b83612965565b6000601f841160018114612a1357600085156129fb5750838201355b600019600387901b1c1916600186901b178355612a6d565b600083815260209020601f19861690835b82811015612a445786850135825560209485019460019092019101612a24565b5086821015612a615760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b612a7e828361291e565b67ffffffffffffffff811115612a9657612a966123b3565b612aaa81612aa4855461275d565b85612965565b6000601f821160018114612ade5760008315612ac65750838201355b600019600385901b1c1916600184901b178555612b38565b600085815260209020601f19841690835b82811015612b0f5786850135825560209485019460019092019101612aef565b5084821015612b2c5760001960f88660031b161c19848701351681555b505060018360011b0185555b50505050612b49602083018361291e565b612b578183600186016129b3565b5050612b66604083018361291e565b611e8c8183600286016129b3565b6000808335601e19843603018112612b8b57600080fd5b830160208101925035905067ffffffffffffffff811115612bab57600080fd5b80360383131561235757600080fd5b604081526000612bcd604083018561258d565b8281036020840152612bdf8485612b74565b60608352612bf1606084018284612797565b915050612c016020860186612b74565b8383036020850152612c14838284612797565b92505050612c256040860186612b74565b8383036040850152612c38838284612797565b98975050505050505050565b6001600160a01b0383168152604060208201819052600090611ffd908301846124be565b6001600160a01b038481168252831660208201526060604082018190526000906125d5908301846124be565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251612cf1818460208701612492565b9190910192915050565b60208152600061230e60208301846124be56fe757064617465506f6f6c4d6574616461746128616464726573732c56656e7573506f6f6c4d6574614461746129616464506f6f6c28737472696e672c616464726573732c75696e743235362c75696e743235362c75696e7432353629a26469706673582212208cce672faf53b5c889509a6420f2f815a187ed6ff1a8730546e98271525564db64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101165760003560e01c8063a3aefa2c116100a2578063e30c397811610071578063e30c397814610267578063eed873c214610278578063f2fde38b14610299578063f36dba38146102ac578063ff94d958146102cc57600080fd5b8063a3aefa2c1461020e578063b4a0bdf31461022e578063c4d66de81461023f578063d88ff1f41461025257600080fd5b80632ba21572116100e95780632ba21572146101ab578063715018a6146101cd57806379ba5097146101d55780637aee632d146101dd5780638da5cb5b146101fd57600080fd5b80630e32cb861461011b5780631cb6bb7e1461013057806323dc8d6414610143578063266e0a7f14610156575b600080fd5b61012e6101293660046122f1565b6102df565b005b61012e61013e36600461235e565b6102f3565b61012e6101513660046123c9565b610440565b61018e610164366004612459565b6001600160a01b03918216600090815260cd60209081526040808320938516835292905220541690565b6040516001600160a01b0390911681526020015b60405180910390f35b6101be6101b93660046122f1565b610b96565b6040516101a2939291906124ea565b61012e610d50565b61012e610d64565b6101f06101eb3660046122f1565b610ddb565b6040516101a2919061257a565b6033546001600160a01b031661018e565b61022161021c3660046122f1565b610ed2565b6040516101a291906125de565b6097546001600160a01b031661018e565b61012e61024d3660046122f1565b6110d5565b61025a6111f1565b6040516101a291906125f1565b6065546001600160a01b031661018e565b61028b610286366004612653565b611392565b6040519081526020016101a2565b61012e6102a73660046122f1565b611552565b6102bf6102ba3660046122f1565b6115c3565b6040516101a291906126c4565b61012e6102da366004612711565b611639565b6102e76118a4565b6102f0816118fe565b50565b6103316040518060400160405280601b81526020017f736574506f6f6c4e616d6528616464726573732c737472696e672900000000008152506119bc565b61033b8282611a56565b6001600160a01b038316600090815260cc60205260408120805490919082906103639061275d565b80601f016020809104026020016040519081016040528092919081815260200182805461038f9061275d565b80156103dc5780601f106103b1576101008083540402835291602001916103dc565b820191906000526020600020905b8154815290600101906020018083116103bf57829003601f168201915b509394506103f3935085925087915086905061217e565b50846001600160a01b03167fa01f2b0df2b143bfb23d4b696c103547a6bec8ca1f56e8e8a483611cb4e23a7e828686604051610431939291906127c0565b60405180910390a25050505050565b61047e6040518060400160405280601981526020017f6164644d61726b6574284164644d61726b6574496e70757429000000000000008152506119bc565b805161048990611aa7565b6104968160800151611aa7565b60008160600151116104fb5760405162461bcd60e51b815260206004820152602360248201527f506f6f6c52656769737472793a20696e697469616c537570706c79206973207a60448201526265726f60e81b60648201526084015b60405180910390fd5b60008160000151905060008190506000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056d91906127e6565b905060008190506000846001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d891906127e6565b6001600160a01b03848116600090815260cc60205260409020600101549192508291166106515760405162461bcd60e51b815260206004820152602160248201527f506f6f6c52656769737472793a20506f6f6c206e6f74207265676973746572656044820152601960fa1b60648201526084016104f2565b6001600160a01b03848116600090815260cd60209081526040808320868516845290915290205416156106fa5760405162461bcd60e51b8152602060048201526044602482018190527f506f6f6c52656769737472793a204d61726b657420616c726561647920616464908201527f656420666f7220617373657420636f6d7074726f6c6c657220636f6d62696e616064820152633a34b7b760e11b608482015260a4016104f2565b6040516332ad3e1360e21b81526001600160a01b03878116600483015284169063cab4f84c90602401600060405180830381600087803b15801561073d57600080fd5b505af1158015610751573d6000803e3d6000fd5b5050505060208701516040808901519051635cc4fdeb60e01b81526001600160a01b0389811660048301526024820193909352604481019190915290841690635cc4fdeb90606401600060405180830381600087803b1580156107b357600080fd5b505af11580156107c7573d6000803e3d6000fd5b5060009250600191506107d79050565b604051908082528060200260200182016040528015610800578160200160208202803683370190505b50604080516001808252818301909252919250600091906020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508960a001518360008151811061086257610862612803565b6020026020010181815250508960c001518260008151811061088657610886612803565b60200260200101818152505088816000815181106108a6576108a6612803565b6001600160a01b03928316602091820292909201015260405163344dabd160e21b81529087169063d136af44906108e39084908790600401612819565b600060405180830381600087803b1580156108fd57600080fd5b505af1158015610911573d6000803e3d6000fd5b505060405163186db48f60e01b81526001600160a01b038916925063186db48f91506109439084908690600401612819565b600060405180830381600087803b15801561095d57600080fd5b505af1158015610971573d6000803e3d6000fd5b5050506001600160a01b03808916600081815260cd602090815260408083208b8616845282528083208054958f166001600160a01b031996871617905560ce82528220805460018101825590835290822001805490931690911790915560608c01519091506109e39086903390611ace565b60405163095ea7b360e01b81526001600160a01b038b81166004830152600060248301529192509086169063095ea7b3906044016020604051808303816000875af1158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5a919061289d565b5060405163095ea7b360e01b81526001600160a01b038a811660048301526024820183905286169063095ea7b3906044016020604051808303816000875af1158015610aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ace919061289d565b5060808b01516040516323323e0360e01b81526001600160a01b03918216600482015260248101839052908b16906323323e03906044016020604051808303816000875af1158015610b24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4891906128bf565b50886001600160a01b0316886001600160a01b03167f7772c85e68debdf74fad87834e2cc05fa763e74faf14de7096da30529065114260405160405180910390a35050505050505050505050565b60c960205260009081526040902080548190610bb19061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdd9061275d565b8015610c2a5780601f10610bff57610100808354040283529160200191610c2a565b820191906000526020600020905b815481529060010190602001808311610c0d57829003601f168201915b505050505090806001018054610c3f9061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6b9061275d565b8015610cb85780601f10610c8d57610100808354040283529160200191610cb8565b820191906000526020600020905b815481529060010190602001808311610c9b57829003601f168201915b505050505090806002018054610ccd9061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610cf99061275d565b8015610d465780601f10610d1b57610100808354040283529160200191610d46565b820191906000526020600020905b815481529060010190602001808311610d2957829003601f168201915b5050505050905083565b610d586118a4565b610d626000611bd3565b565b60655433906001600160a01b03168114610dd25760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016104f2565b6102f081611bd3565b610de3612202565b6001600160a01b038216600090815260cc602052604090819020815160a08101909252805482908290610e159061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610e419061275d565b8015610e8e5780601f10610e6357610100808354040283529160200191610e8e565b820191906000526020600020905b815481529060010190602001808311610e7157829003601f168201915b505050918352505060018201546001600160a01b03908116602083015260028301541660408201526003820154606082015260049091015460809091015292915050565b610ef660405180606001604052806060815260200160608152602001606081525090565b6001600160a01b038216600090815260c9602052604090819020815160608101909252805482908290610f289061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f549061275d565b8015610fa15780601f10610f7657610100808354040283529160200191610fa1565b820191906000526020600020905b815481529060010190602001808311610f8457829003601f168201915b50505050508152602001600182018054610fba9061275d565b80601f0160208091040260200160405190810160405280929190818152602001828054610fe69061275d565b80156110335780601f1061100857610100808354040283529160200191611033565b820191906000526020600020905b81548152906001019060200180831161101657829003601f168201915b5050505050815260200160028201805461104c9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546110789061275d565b80156110c55780601f1061109a576101008083540402835291602001916110c5565b820191906000526020600020905b8154815290600101906020018083116110a857829003601f168201915b5050505050815250509050919050565b600054610100900460ff16158080156110f55750600054600160ff909116105b8061110f5750303b15801561110f575060005460ff166001145b6111725760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016104f2565b6000805460ff191660011790558015611195576000805461ff0019166101001790555b61119d611bec565b6111a682611c1b565b80156111ed576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a15b5050565b60cb5460609060008167ffffffffffffffff811115611212576112126123b3565b60405190808252806020026020018201604052801561124b57816020015b611238612202565b8152602001906001900390816112305790505b50905060015b82811161138b57600081815260ca60209081526040808320546001600160a01b031680845260cc90925291829020825160a0810190935280549192918290829061129a9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546112c69061275d565b80156113135780601f106112e857610100808354040283529160200191611313565b820191906000526020600020905b8154815290600101906020018083116112f657829003601f168201915b50505091835250506001828101546001600160a01b039081166020840152600284015416604083015260038301546060830152600490920154608090910152849061135e90856128ee565b8151811061136e5761136e612803565b6020026020010181905250508061138490612905565b9050611251565b5092915050565b60006113b56040518060600160405280602f8152602001612d3c602f91396119bc565b6113be85611aa7565b611428856001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142391906127e6565b611aa7565b6000611435888888611c42565b60405163091a474b60e11b8152600481018790529091506001600160a01b038716906312348e9690602401600060405180830381600087803b15801561147a57600080fd5b505af115801561148e573d6000803e3d6000fd5b505060405163a843108160e01b8152600481018790526001600160a01b038916925063a84310819150602401600060405180830381600087803b1580156114d457600080fd5b505af11580156114e8573d6000803e3d6000fd5b5050604051631482db1d60e21b8152600481018690526001600160a01b038916925063520b6c749150602401600060405180830381600087803b15801561152e57600080fd5b505af1158015611542573d6000803e3d6000fd5b50929a9950505050505050505050565b61155a6118a4565b606580546001600160a01b0383166001600160a01b0319909116811790915561158b6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6001600160a01b038116600090815260ce602090815260409182902080548351818402810184019094528084526060939283018282801561162d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161160f575b50505050509050919050565b61165a6040518060600160405280602d8152602001612d0f602d91396119bc565b6001600160a01b038216600090815260c9602052604080822081516060810190925280548290829061168b9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546116b79061275d565b80156117045780601f106116d957610100808354040283529160200191611704565b820191906000526020600020905b8154815290600101906020018083116116e757829003601f168201915b5050505050815260200160018201805461171d9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546117499061275d565b80156117965780601f1061176b57610100808354040283529160200191611796565b820191906000526020600020905b81548152906001019060200180831161177957829003601f168201915b505050505081526020016002820180546117af9061275d565b80601f01602080910402602001604051908101604052809291908181526020018280546117db9061275d565b80156118285780601f106117fd57610100808354040283529160200191611828565b820191906000526020600020905b81548152906001019060200180831161180b57829003601f168201915b505050919092525050506001600160a01b038416600090815260c96020526040902090915082906118598282612a74565b905050826001600160a01b03167f8f91f3b5d20b61744ed591c43346d4514ee5c2ffced5fc3795bb13c6f95181478284604051611897929190612bba565b60405180910390a2505050565b6033546001600160a01b03163314610d625760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f2565b6001600160a01b0381166119625760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b60648201526084016104f2565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e4565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906119ef9033908690600401612c44565b602060405180830381865afa158015611a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a30919061289d565b9050806111ed57333083604051634a3fa29360e01b81526004016104f293929190612c68565b60648111156111ed5760405162461bcd60e51b815260206004820152601860248201527f506f6f6c2773206e616d6520697320746f6f206c61726765000000000000000060448201526064016104f2565b6001600160a01b0381166102f0576040516342bcdf7f60e11b815260040160405180910390fd5b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a0823190602401602060405180830381865afa158015611b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3b91906128bf565b9050611b526001600160a01b038616853086611e32565b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015611b99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbd91906128bf565b9050611bc982826128ee565b9695505050505050565b606580546001600160a01b03191690556102f081611e92565b600054610100900460ff16611c135760405162461bcd60e51b81526004016104f290612c94565b610d62611ee4565b600054610100900460ff166102e75760405162461bcd60e51b81526004016104f290612c94565b6001600160a01b03808216600090815260cc602052604081206001810154919290911615611cce5760405162461bcd60e51b815260206004820152603360248201527f506f6f6c52656769737472793a20506f6f6c20616c7265616479206578697374604482015272399034b7103a3432903234b932b1ba37b93c9760691b60648201526084016104f2565b611cd88585611a56565b60cb60008154611ce790612905565b9091555060cb546040805160c06020601f8901819004028201810190925260a081018781526000928291908a908a908190850183828082843760009201829052509385525050336020808501919091526001600160a01b038a1660408086018290524360608701524260809096019590955287845260ca825284842080546001600160a01b03191682179055835260cc8152929091208351805194955085949193611d9793508492910190612243565b5060208201516001820180546001600160a01b03199081166001600160a01b039384161790915560408085015160028501805490931690841617909155606084015160038401556080909301516004909201919091559051908616907f53ec2a1d9645c4631472dabcf6d255f5f2971baa64321235b1610d91c692928e90611e2090849061257a565b60405180910390a25095945050505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611e8c908590611f14565b50505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611f0b5760405162461bcd60e51b81526004016104f290612c94565b610d6233611bd3565b6000611f69826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611fee9092919063ffffffff16565b9050805160001480611f8a575080806020019051810190611f8a919061289d565b611fe95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104f2565b505050565b6060611ffd8484600085612005565b949350505050565b6060824710156120665760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016104f2565b600080866001600160a01b031685876040516120829190612cdf565b60006040518083038185875af1925050503d80600081146120bf576040519150601f19603f3d011682016040523d82523d6000602084013e6120c4565b606091505b50915091506120d5878383876120e0565b979650505050505050565b6060831561214f578251600003612148576001600160a01b0385163b6121485760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104f2565b5081611ffd565b611ffd83838151156121645781518083602001fd5b8060405162461bcd60e51b81526004016104f29190612cfb565b82805461218a9061275d565b90600052602060002090601f0160209004810192826121ac57600085556121f2565b82601f106121c55782800160ff198235161785556121f2565b828001600101855582156121f2579182015b828111156121f25782358255916020019190600101906121d7565b506121fe9291506122b7565b5090565b6040518060a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081525090565b82805461224f9061275d565b90600052602060002090601f01602090048101928261227157600085556121f2565b82601f1061228a57805160ff19168380011785556121f2565b828001600101855582156121f2579182015b828111156121f257825182559160200191906001019061229c565b5b808211156121fe57600081556001016122b8565b6001600160a01b03811681146102f057600080fd5b80356122ec816122cc565b919050565b60006020828403121561230357600080fd5b813561230e816122cc565b9392505050565b60008083601f84011261232757600080fd5b50813567ffffffffffffffff81111561233f57600080fd5b60208301915083602082850101111561235757600080fd5b9250929050565b60008060006040848603121561237357600080fd5b833561237e816122cc565b9250602084013567ffffffffffffffff81111561239a57600080fd5b6123a686828701612315565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b600060e082840312156123db57600080fd5b60405160e0810181811067ffffffffffffffff821117156123fe576123fe6123b3565b60405261240a836122e1565b8152602083013560208201526040830135604082015260608301356060820152612436608084016122e1565b608082015260a083013560a082015260c083013560c08201528091505092915050565b6000806040838503121561246c57600080fd5b8235612477816122cc565b91506020830135612487816122cc565b809150509250929050565b60005b838110156124ad578181015183820152602001612495565b83811115611e8c5750506000910152565b600081518084526124d6816020860160208601612492565b601f01601f19169290920160200192915050565b6060815260006124fd60608301866124be565b828103602084015261250f81866124be565b90508281036040840152611bc981856124be565b6000815160a0845261253860a08501826124be565b9050602083015160018060a01b038082166020870152806040860151166040870152505060608301516060850152608083015160808501528091505092915050565b60208152600061230e6020830184612523565b60008151606084526125a260608501826124be565b9050602083015184820360208601526125bb82826124be565b915050604083015184820360408601526125d582826124be565b95945050505050565b60208152600061230e602083018461258d565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561264657603f19888603018452612634858351612523565b94509285019290850190600101612618565b5092979650505050505050565b60008060008060008060a0878903121561266c57600080fd5b863567ffffffffffffffff81111561268357600080fd5b61268f89828a01612315565b90975095505060208701356126a3816122cc565b95989497509495604081013595506060810135946080909101359350915050565b6020808252825182820181905260009190848201906040850190845b818110156127055783516001600160a01b0316835292840192918401916001016126e0565b50909695505050505050565b6000806040838503121561272457600080fd5b823561272f816122cc565b9150602083013567ffffffffffffffff81111561274b57600080fd5b83016060818603121561248757600080fd5b600181811c9082168061277157607f821691505b60208210810361279157634e487b7160e01b600052602260045260246000fd5b50919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040815260006127d360408301866124be565b8281036020840152611bc9818587612797565b6000602082840312156127f857600080fd5b815161230e816122cc565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b8281101561285b5781516001600160a01b031684529284019290840190600101612836565b5050508381038285015284518082528583019183019060005b8181101561289057835183529284019291840191600101612874565b5090979650505050505050565b6000602082840312156128af57600080fd5b8151801515811461230e57600080fd5b6000602082840312156128d157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082821015612900576129006128d8565b500390565b600060018201612917576129176128d8565b5060010190565b6000808335601e1984360301811261293557600080fd5b83018035915067ffffffffffffffff82111561295057600080fd5b60200191503681900382131561235757600080fd5b601f821115611fe957600081815260208120601f850160051c8101602086101561298c5750805b601f850160051c820191505b818110156129ab57828155600101612998565b505050505050565b67ffffffffffffffff8311156129cb576129cb6123b3565b6129df836129d9835461275d565b83612965565b6000601f841160018114612a1357600085156129fb5750838201355b600019600387901b1c1916600186901b178355612a6d565b600083815260209020601f19861690835b82811015612a445786850135825560209485019460019092019101612a24565b5086821015612a615760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b612a7e828361291e565b67ffffffffffffffff811115612a9657612a966123b3565b612aaa81612aa4855461275d565b85612965565b6000601f821160018114612ade5760008315612ac65750838201355b600019600385901b1c1916600184901b178555612b38565b600085815260209020601f19841690835b82811015612b0f5786850135825560209485019460019092019101612aef565b5084821015612b2c5760001960f88660031b161c19848701351681555b505060018360011b0185555b50505050612b49602083018361291e565b612b578183600186016129b3565b5050612b66604083018361291e565b611e8c8183600286016129b3565b6000808335601e19843603018112612b8b57600080fd5b830160208101925035905067ffffffffffffffff811115612bab57600080fd5b80360383131561235757600080fd5b604081526000612bcd604083018561258d565b8281036020840152612bdf8485612b74565b60608352612bf1606084018284612797565b915050612c016020860186612b74565b8383036020850152612c14838284612797565b92505050612c256040860186612b74565b8383036040850152612c38838284612797565b98975050505050505050565b6001600160a01b0383168152604060208201819052600090611ffd908301846124be565b6001600160a01b038481168252831660208201526060604082018190526000906125d5908301846124be565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251612cf1818460208701612492565b9190910192915050565b60208152600061230e60208301846124be56fe757064617465506f6f6c4d6574616461746128616464726573732c56656e7573506f6f6c4d6574614461746129616464506f6f6c28737472696e672c616464726573732c75696e743235362c75696e743235362c75696e7432353629a26469706673582212208cce672faf53b5c889509a6420f2f815a187ed6ff1a8730546e98271525564db64736f6c634300080d0033", + "devdoc": { + "author": "Venus", + "kind": "dev", + "methods": { + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "addMarket((address,uint256,uint256,uint256,address,uint256,uint256))": { + "custom:error": "ZeroAddressNotAllowed is thrown when vToken address is zeroZeroAddressNotAllowed is thrown when vTokenReceiver address is zero", + "params": { + "input": "The structure describing the parameters for adding a market to a pool" + } + }, + "addPool(string,address,uint256,uint256,uint256)": { + "custom:error": "ZeroAddressNotAllowed is thrown when Comptroller address is zeroZeroAddressNotAllowed is thrown when price oracle address is zero", + "details": "Price oracle must be configured before adding a pool", + "params": { + "closeFactor": "The pool's close factor (scaled by 1e18)", + "comptroller": "Pool's Comptroller contract", + "liquidationIncentive": "The pool's liquidation incentive (scaled by 1e18)", + "minLiquidatableCollateral": "Minimal collateral for regular (non-batch) liquidations flow", + "name": "The name of the pool" + }, + "returns": { + "index": "The index of the registered Venus pool" + } + }, + "constructor": { + "custom:oz-upgrades-unsafe-allow": "constructor" + }, + "getAllPools()": { + "details": "This function is not designed to be called in a transaction: it is too gas-intensive", + "returns": { + "_0": "A list of all pools within PoolRegistry, with details for each pool" + } + }, + "getPoolByComptroller(address)": { + "params": { + "comptroller": "The comptroller proxy address associated to the pool" + }, + "returns": { + "_0": "Returns Venus pool" + } + }, + "getVenusPoolMetadata(address)": { + "params": { + "comptroller": "comptroller of Venus pool" + }, + "returns": { + "_0": "Returns Metadata of Venus pool" + } + }, + "initialize(address)": { + "params": { + "accessControlManager_": "AccessControlManager contract address" + } + }, + "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" + } + }, + "setPoolName(address,string)": { + "params": { + "comptroller": "Pool's Comptroller", + "name": "New pool name" + } + }, + "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." + }, + "updatePoolMetadata(address,(string,string,string))": { + "params": { + "comptroller": "Pool's Comptroller", + "metadata_": "New pool metadata" + } + } + }, + "stateVariables": { + "_numberOfPools": { + "details": "Total number of pools created." + }, + "_poolByComptroller": { + "details": "Maps comptroller address to Venus pool Index." + }, + "_poolsByID": { + "details": "Maps pool ID to pool's comptroller address" + }, + "_supportedPools": { + "details": "Maps asset to list of supported pools." + }, + "_vTokens": { + "details": "Maps pool's comptroller address to asset to vToken." + } + }, + "title": "PoolRegistry", + "version": 1 + }, + "userdoc": { + "errors": { + "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": { + "MarketAdded(address,address)": { + "notice": "Emitted when a Market is added to the pool." + }, + "NewAccessControlManager(address,address)": { + "notice": "Emitted when access control manager contract address is changed" + }, + "PoolMetadataUpdated(address,(string,string,string),(string,string,string))": { + "notice": "Emitted when a pool metadata is updated." + }, + "PoolNameSet(address,string,string)": { + "notice": "Emitted when a pool name is set." + }, + "PoolRegistered(address,(string,address,address,uint256,uint256))": { + "notice": "Emitted when a new Venus pool is added to the directory." + } + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "Returns the address of the access control manager contract" + }, + "addMarket((address,uint256,uint256,uint256,address,uint256,uint256))": { + "notice": "Add a market to an existing pool and then mint to provide initial supply" + }, + "addPool(string,address,uint256,uint256,uint256)": { + "notice": "Adds a new Venus pool to the directory" + }, + "getAllPools()": { + "notice": "Returns arrays of all Venus pools' data" + }, + "getPoolsSupportedByAsset(address)": { + "notice": "Get the addresss of the Pools supported that include a market for the provided asset" + }, + "getVTokenForAsset(address,address)": { + "notice": "Get the address of the VToken contract in the Pool where the underlying token is the provided asset" + }, + "initialize(address)": { + "notice": "Initializes the deployer to owner" + }, + "metadata(address)": { + "notice": "Maps pool's comptroller address to metadata." + }, + "setAccessControlManager(address)": { + "notice": "Sets the address of AccessControlManager" + }, + "setPoolName(address,string)": { + "notice": "Modify existing Venus pool name" + }, + "updatePoolMetadata(address,(string,string,string))": { + "notice": "Update metadata of an existing pool" + } + }, + "notice": "The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required metadata, and providing the getter methods to get information on the pools. Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools. It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`) and setting pool name (`setPoolName`). The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's comptroller address. `_poolsByID` is used to iterate through all of the pools. PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by asset is retrieved by calling `getPoolsSupportedByAsset`. PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with specific assets and custom risk management configurations according to their markets.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 290, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 293, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1397, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 162, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 282, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 71, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_pendingOwner", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 150, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 5019, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_accessControlManager", + "offset": 0, + "slot": "151", + "type": "t_contract(IAccessControlManagerV8)5204" + }, + { + "astId": 5024, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 14135, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "metadata", + "offset": 0, + "slot": "201", + "type": "t_mapping(t_address,t_struct(VenusPoolMetaData)14879_storage)" + }, + { + "astId": 14140, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_poolsByID", + "offset": 0, + "slot": "202", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 14143, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_numberOfPools", + "offset": 0, + "slot": "203", + "type": "t_uint256" + }, + { + "astId": 14149, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_poolByComptroller", + "offset": 0, + "slot": "204", + "type": "t_mapping(t_address,t_struct(VenusPool)14872_storage)" + }, + { + "astId": 14156, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_vTokens", + "offset": 0, + "slot": "205", + "type": "t_mapping(t_address,t_mapping(t_address,t_address))" + }, + { + "astId": 14162, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "_supportedPools", + "offset": 0, + "slot": "206", + "type": "t_mapping(t_address,t_array(t_address)dyn_storage)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "base": "t_address", + "encoding": "dynamic_array", + "label": "address[]", + "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)5204": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_array(t_address)dyn_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address[])", + "numberOfBytes": "32", + "value": "t_array(t_address)dyn_storage" + }, + "t_mapping(t_address,t_mapping(t_address,t_address))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => address))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_address)" + }, + "t_mapping(t_address,t_struct(VenusPool)14872_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct PoolRegistryInterface.VenusPool)", + "numberOfBytes": "32", + "value": "t_struct(VenusPool)14872_storage" + }, + "t_mapping(t_address,t_struct(VenusPoolMetaData)14879_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct PoolRegistryInterface.VenusPoolMetaData)", + "numberOfBytes": "32", + "value": "t_struct(VenusPoolMetaData)14879_storage" + }, + "t_mapping(t_uint256,t_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(VenusPool)14872_storage": { + "encoding": "inplace", + "label": "struct PoolRegistryInterface.VenusPool", + "members": [ + { + "astId": 14863, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "name", + "offset": 0, + "slot": "0", + "type": "t_string_storage" + }, + { + "astId": 14865, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "creator", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 14867, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "comptroller", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 14869, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "blockPosted", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 14871, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "timestampPosted", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "numberOfBytes": "160" + }, + "t_struct(VenusPoolMetaData)14879_storage": { + "encoding": "inplace", + "label": "struct PoolRegistryInterface.VenusPoolMetaData", + "members": [ + { + "astId": 14874, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "category", + "offset": 0, + "slot": "0", + "type": "t_string_storage" + }, + { + "astId": 14876, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "logoURL", + "offset": 0, + "slot": "1", + "type": "t_string_storage" + }, + { + "astId": 14878, + "contract": "contracts/Pool/PoolRegistry.sol:PoolRegistry", + "label": "description", + "offset": 0, + "slot": "2", + "type": "t_string_storage" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} diff --git a/deployments/bsctestnet/ProtocolShareReserve_Proxy.json b/deployments/sepolia/PoolRegistry_Proxy.json similarity index 94% rename from deployments/bsctestnet/ProtocolShareReserve_Proxy.json rename to deployments/sepolia/PoolRegistry_Proxy.json index 87f72679c..ef1780ffe 100644 --- a/deployments/bsctestnet/ProtocolShareReserve_Proxy.json +++ b/deployments/sepolia/PoolRegistry_Proxy.json @@ -1,5 +1,5 @@ { - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "abi": [ { "inputs": [ @@ -146,74 +146,84 @@ "type": "receive" } ], - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", "receipt": { "to": null, - "from": "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706", - "contractAddress": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", - "transactionIndex": 1, - "gasUsed": "817670", - "logsBloom": "0x10000000000000000000000000000000400000040000000000800008000000000000000000000040000000000000000000000000000001000000000000004000000000000000000000000000000002000001000000001000000000000000000000000008020000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000000000080000000000000800000000000000000000000000000000400000000000000000000000000000000004000000020000000000000000000040000000000000400000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943", - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x758f5715d817e02857Ba40889251201A5aE3E186", + "transactionIndex": 53, + "gasUsed": "796718", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000000000000000000000000000200000000000000008000000010000000000000000000000002000001000000000000002000000000000000080000020000000000000000000800000000800000000000000000000000400000000000000000000800000000000000000000000080000000000000800000000000000000000000000000000400000000000000800000000400000000000000000020000000000000000110040000000000000400000000000000000020000000020000000000000000000000000000000800000000000000000000000000", + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746", + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", "logs": [ { - "transactionIndex": 1, - "blockNumber": 33267957, - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", - "0x0000000000000000000000000bbea4b14f475bf5eb60fc2b0ca90d3d089ef833" + "0x0000000000000000000000003213607db41319e32c3706116adf1ae890e4083a" ], "data": "0x", - "logIndex": 0, - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943" + "logIndex": 53, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" }, { - "transactionIndex": 1, - "blockNumber": 33267957, - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000002ce1d0ffd7e869d9df33e28552b12ddded326706" + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" ], "data": "0x", - "logIndex": 1, - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943" + "logIndex": 54, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" }, { - "transactionIndex": 1, - "blockNumber": 33267957, - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 55, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" + }, + { + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 2, - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943" + "logIndex": 56, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" }, { - "transactionIndex": 1, - "blockNumber": 33267957, - "transactionHash": "0xe0ff17919e19d8e44e50d647288f605fdff215295c89f394c5a4f069d2ad15b4", - "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "transactionIndex": 53, + "blockNumber": 4776616, + "transactionHash": "0x486753ed51334b8fca2664262500643bc573cb77ce50a980398da2532d854781", + "address": "0x758f5715d817e02857Ba40889251201A5aE3E186", "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007877ffd62649b6a1557b55d4c20fcbab17344c91", - "logIndex": 3, - "blockHash": "0x50c0fad5b3f68f8dabd9788b5613c7cc0d5a0485220f4eb90a19054bb7174943" + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e98a3110929c6650c73031756288ec518f65e846", + "logIndex": 57, + "blockHash": "0x7e214af82d33a86f6f88d1f7e95aea28cd64246fa52fc620bc0a259a59926746" } ], - "blockNumber": 33267957, - "cumulativeGasUsed": "848911", + "blockNumber": 4776616, + "cumulativeGasUsed": "10451599", "status": 1, "byzantium": true }, "args": [ - "0x0Bbea4B14f475bF5eb60Fc2b0Ca90d3d089Ef833", - "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", - "0x485cc9550000000000000000000000008b293600c50d6fbdc6ed4251cc75ece29880276f000000000000000000000000487cef72dacabd7e12e633bb3b63815a386f7012" + "0x3213607Db41319E32C3706116Adf1Ae890E4083A", + "0xe98a3110929c6650c73031756288Ec518f65e846", + "0xc4d66de8000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96" ], "numDeployments": 1, "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", diff --git a/deployments/sepolia/RewardsDistributorImpl.json b/deployments/sepolia/RewardsDistributorImpl.json new file mode 100644 index 000000000..5fe24788b --- /dev/null +++ b/deployments/sepolia/RewardsDistributorImpl.json @@ -0,0 +1,1545 @@ +{ + "address": "0xaA0472719984e799aC11D01C16D3c6B0F8d5C39B", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAccrued", + "type": "uint256" + } + ], + "name": "ContributorRewardsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketInitialized", + "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": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "RewardTokenBorrowIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardTokenGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "RewardTokenSupplyIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenSupplySpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "SupplyLastRewardingBlockUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "INITIAL_INDEX", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "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": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "distributeBorrowerRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", + "type": "address" + } + ], + "name": "distributeSupplierRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "grantRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract Comptroller", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "initializeMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastContributorBlock", + "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": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenContributorSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardTokenSpeed", + "type": "uint256" + } + ], + "name": "setContributorRewardTokenSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" + } + ], + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "setRewardTokenSpeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + } + ], + "name": "updateContributorRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updateRewardTokenSupplyIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xc91d7038e49eb8dac462339be6de79b9fa21fef724aa52b2f68347901b6dfb10", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xaA0472719984e799aC11D01C16D3c6B0F8d5C39B", + "transactionIndex": 30, + "gasUsed": "2651090", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040080000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000", + "blockHash": "0x70819f024767b668c978eeea38324a32a15108ecf3b3d653d6eedd25e3cc6602", + "transactionHash": "0xc91d7038e49eb8dac462339be6de79b9fa21fef724aa52b2f68347901b6dfb10", + "logs": [ + { + "transactionIndex": 30, + "blockNumber": 4776645, + "transactionHash": "0xc91d7038e49eb8dac462339be6de79b9fa21fef724aa52b2f68347901b6dfb10", + "address": "0xaA0472719984e799aC11D01C16D3c6B0F8d5C39B", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", + "logIndex": 45, + "blockHash": "0x70819f024767b668c978eeea38324a32a15108ecf3b3d653d6eedd25e3cc6602" + } + ], + "blockNumber": 4776645, + "cumulativeGasUsed": "10245415", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"newBlock\",\"type\":\"uint32\"}],\"name\":\"BorrowLastRewardingBlockUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"ContributorRewardTokenSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardAccrued\",\"type\":\"uint256\"}],\"name\":\"ContributorRewardsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardTokenDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardTokenTotal\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardTokenBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerRewardToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardTokenDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardTokenTotal\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardTokenSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierRewardToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketInitialized\",\"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\":\"vToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"mantissa\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"struct ExponentialNoError.Exp\",\"name\":\"marketBorrowIndex\",\"type\":\"tuple\"}],\"name\":\"RewardTokenBorrowIndexUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"RewardTokenBorrowSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"RewardTokenGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"RewardTokenSupplyIndexUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"RewardTokenSupplySpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"newBlock\",\"type\":\"uint32\"}],\"name\":\"SupplyLastRewardingBlockUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"INITIAL_INDEX\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"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\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"claimRewardToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimRewardToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"mantissa\",\"type\":\"uint256\"}],\"internalType\":\"struct ExponentialNoError.Exp\",\"name\":\"marketBorrowIndex\",\"type\":\"tuple\"}],\"name\":\"distributeBorrowerRewardToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"}],\"name\":\"distributeSupplierRewardToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"grantRewardToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract Comptroller\",\"name\":\"comptroller_\",\"type\":\"address\"},{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"rewardToken_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"loopsLimit_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"initializeMarket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastContributorBlock\",\"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\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rewardToken\",\"outputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokenAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokenBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokenBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastRewardingBlock\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokenBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokenContributorSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokenSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokenSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokenSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"lastRewardingBlock\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"rewardTokenSpeed\",\"type\":\"uint256\"}],\"name\":\"setContributorRewardTokenSpeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint32[]\",\"name\":\"supplyLastRewardingBlocks\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32[]\",\"name\":\"borrowLastRewardingBlocks\",\"type\":\"uint32[]\"}],\"name\":\"setLastRewardingBlocks\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"supplySpeeds\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"borrowSpeeds\",\"type\":\"uint256[]\"}],\"name\":\"setRewardTokenSpeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"contributor\",\"type\":\"address\"}],\"name\":\"updateContributorRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"mantissa\",\"type\":\"uint256\"}],\"internalType\":\"struct ExponentialNoError.Exp\",\"name\":\"marketBorrowIndex\",\"type\":\"tuple\"}],\"name\":\"updateRewardTokenBorrowIndex\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"updateRewardTokenSupplyIndex\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"claimRewardToken(address)\":{\"params\":{\"holder\":\"The address to claim REWARD TOKEN for\"}},\"claimRewardToken(address,address[])\":{\"params\":{\"holder\":\"The address to claim REWARD TOKEN for\",\"vTokens\":\"The list of markets to claim REWARD TOKEN in\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"distributeBorrowerRewardToken(address,address,(uint256))\":{\"details\":\"This function should only be called when the user has a borrow position in the market (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook) We avoid an external call to check if they are in the market to save gas because this function is called in many places\",\"params\":{\"borrower\":\"The address of the borrower to distribute REWARD TOKEN to\",\"marketBorrowIndex\":\"The current global borrow index of vToken\",\"vToken\":\"The market in which the borrower is interacting\"}},\"grantRewardToken(address,uint256)\":{\"details\":\"Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\",\"params\":{\"amount\":\"The amount of REWARD TOKEN to (possibly) transfer\",\"recipient\":\"The address of the recipient to transfer REWARD TOKEN to\"}},\"initialize(address,address,uint256,address)\":{\"details\":\"Initializes the deployer to owner\",\"params\":{\"accessControlManager_\":\"AccessControlManager contract address\",\"comptroller_\":\"Comptroller to attach the reward distributor to\",\"loopsLimit_\":\"Maximum number of iterations for the loops in this contract\",\"rewardToken_\":\"Reward token to distribute\"}},\"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\"}},\"setContributorRewardTokenSpeed(address,uint256)\":{\"params\":{\"contributor\":\"The contributor whose REWARD TOKEN speed to update\",\"rewardTokenSpeed\":\"New REWARD TOKEN speed for contributor\"}},\"setLastRewardingBlocks(address[],uint32[],uint32[])\":{\"params\":{\"borrowLastRewardingBlocks\":\"New borrow-side REWARD TOKEN last rewarding block for the corresponding market\",\"supplyLastRewardingBlocks\":\"New supply-side REWARD TOKEN last rewarding block for the corresponding market\",\"vTokens\":\"The markets whose REWARD TOKEN last rewarding block to update\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setRewardTokenSpeeds(address[],uint256[],uint256[])\":{\"params\":{\"borrowSpeeds\":\"New borrow-side REWARD TOKEN speed for the corresponding market\",\"supplySpeeds\":\"New supply-side REWARD TOKEN speed for the corresponding market\",\"vTokens\":\"The markets whose REWARD TOKEN speed to update\"}},\"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.\"},\"updateContributorRewards(address)\":{\"params\":{\"contributor\":\"The address to calculate contributor rewards for\"}}},\"title\":\"`RewardsDistributor`\",\"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\"}]},\"events\":{\"BorrowLastRewardingBlockUpdated(address,uint32)\":{\"notice\":\"Emitted when a reward token last rewarding block for borrow is updated\"},\"ContributorRewardTokenSpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new REWARD TOKEN speed is set for a contributor\"},\"ContributorRewardsUpdated(address,uint256)\":{\"notice\":\"Emitted when a reward for contributor is updated\"},\"DistributedBorrowerRewardToken(address,address,uint256,uint256,uint256)\":{\"notice\":\"Emitted when REWARD TOKEN is distributed to a borrower\"},\"DistributedSupplierRewardToken(address,address,uint256,uint256,uint256)\":{\"notice\":\"Emitted when REWARD TOKEN is distributed to a supplier\"},\"MarketInitialized(address)\":{\"notice\":\"Emitted when a market is initialized\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"RewardTokenBorrowIndexUpdated(address,(uint256))\":{\"notice\":\"Emitted when a reward token borrow index is updated\"},\"RewardTokenBorrowSpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\"},\"RewardTokenGranted(address,uint256)\":{\"notice\":\"Emitted when REWARD TOKEN is granted by admin\"},\"RewardTokenSupplyIndexUpdated(address)\":{\"notice\":\"Emitted when a reward token supply index is updated\"},\"RewardTokenSupplySpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\"},\"SupplyLastRewardingBlockUpdated(address,uint32)\":{\"notice\":\"Emitted when a reward token last rewarding block for supply is updated\"}},\"kind\":\"user\",\"methods\":{\"INITIAL_INDEX()\":{\"notice\":\"The initial REWARD TOKEN index for a market\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"claimRewardToken(address)\":{\"notice\":\"Claim all the rewardToken accrued by holder in all markets\"},\"claimRewardToken(address,address[])\":{\"notice\":\"Claim all the rewardToken accrued by holder in the specified markets\"},\"distributeBorrowerRewardToken(address,address,(uint256))\":{\"notice\":\"Calculate reward token accrued by a borrower and possibly transfer it to them Borrowers will begin to accrue after the first interaction with the protocol.\"},\"grantRewardToken(address,uint256)\":{\"notice\":\"Transfer REWARD TOKEN to the recipient\"},\"initialize(address,address,uint256,address)\":{\"notice\":\"RewardsDistributor initializer\"},\"lastContributorBlock(address)\":{\"notice\":\"Last block at which a contributor's REWARD TOKEN rewards have been allocated\"},\"rewardTokenAccrued(address)\":{\"notice\":\"The REWARD TOKEN accrued but not yet transferred to each user\"},\"rewardTokenBorrowSpeeds(address)\":{\"notice\":\"The rate at which rewardToken is distributed to the corresponding borrow market (per block)\"},\"rewardTokenBorrowState(address)\":{\"notice\":\"The REWARD TOKEN market borrow state for each market\"},\"rewardTokenBorrowerIndex(address,address)\":{\"notice\":\"The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\"},\"rewardTokenContributorSpeeds(address)\":{\"notice\":\"The portion of REWARD TOKEN that each contributor receives per block\"},\"rewardTokenSupplierIndex(address,address)\":{\"notice\":\"The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\"},\"rewardTokenSupplySpeeds(address)\":{\"notice\":\"The rate at which rewardToken is distributed to the corresponding supply market (per block)\"},\"rewardTokenSupplyState(address)\":{\"notice\":\"The REWARD TOKEN market supply state for each market\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setContributorRewardTokenSpeed(address,uint256)\":{\"notice\":\"Set REWARD TOKEN speed for a single contributor\"},\"setLastRewardingBlocks(address[],uint32[],uint32[])\":{\"notice\":\"Set REWARD TOKEN last rewarding block for the specified markets\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setRewardTokenSpeeds(address[],uint256[],uint256[])\":{\"notice\":\"Set REWARD TOKEN borrow and supply speeds for the specified markets\"},\"updateContributorRewards(address)\":{\"notice\":\"Calculate additional accrued REWARD TOKEN for a contributor since last accrual\"}},\"notice\":\"Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol. Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool. Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward token to be released each block for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting their contributor reward token speed, which similarly allocates a fixed amount of reward token per block. The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Rewards/RewardsDistributor.sol\":\"RewardsDistributor\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"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/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.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"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/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/protocol-reserve/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/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor is changed by admin\\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow.\\n * @param vTokenAddress The address of the asset to be removed\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return NO_ERROR;\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\n _checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = accountAssets[user];\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = accountAssets[borrower];\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n _ensureMaxLoops(numMarkets);\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Enables forced liquidations for a market. If forced liquidation is enabled,\\n * borrows in the market may be liquidated regardless of the account liquidity\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall Hypothetical account shortfall below collateral requirements\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Check if a market is marked as listed (active)\\n * @param vToken vToken Address for the market to check\\n * @return listed True if listed otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].isListed;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n VToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the market specified, otherwise false.\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = accountAssets[account];\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n }\\n\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = accountAssets[account];\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x42f9cceba5f1b4d82047f930a7049740d13ab36004bb1a58b462b9e111c08665\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x44c67531518072db11bf6eafe29499073724346a7855579b09a9da049742d879\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // Multiplier representing the most one can borrow against their collateral in this market.\\n // For instance, 0.9 to allow borrowing 90% of collateral value.\\n // Must be between 0 and 1, and stored as a mantissa.\\n uint256 collateralFactorMantissa;\\n // Multiplier representing the collateralization after which the borrow is eligible\\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n // value. Must be between 0 and collateral factor, stored as a mantissa.\\n uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\n enum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n }\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint256 public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n /**\\n * @notice Official mapping of vTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\\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\":\"0xdfc033911c20e09516110ae3f94740b4be1a065baee4412a708e25a25568eac8\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x3f8ec4e18bca1fdf8619966f4f6e095e205517a78f8c741b87fe82125754f96f\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x1f17b8e3fdd89657d488250140f6d6abeb04f2b822467139687487f9c1dbe397\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"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\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each block for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller private comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlock(address[],uint32[],uint32[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumber();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\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 */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumber = getBlockNumber();\\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n function getBlockNumber() public view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumber();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplyIndex = supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowIndex = borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\\n blockNumber = supplyState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\\n\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n supplyState.index = safe224(\\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n supplyState.block = blockNumber;\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\\n blockNumber = borrowState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n borrowState.index = safe224(\\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n borrowState.block = blockNumber;\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0x598aad1a12d6a895f82a8b619000099efe53994fe89522b41adaa68819fac652\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n /**\\n * Reentrancy Guard **\\n */\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\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 /**\\n * @notice Construct a new money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\n );\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n _borrowFresh(msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == _getBlockNumber()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockDelta block difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockDelta;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return amount The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return rate The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this v\\n * @return rate The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number */\\n uint256 currentBlockNumber = _getBlockNumber();\\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentBlockNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n _reduceReservesFresh(totalReservesNew);\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is sending the assets for supply\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `_doTransferIn` for the minter and the mintAmount.\\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n }\\n\\n /**\\n * @notice User redeems vTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n */\\n function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\\n * On success, the vToken has redeemAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(redeemer, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrower User who borrows the assets\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the borrower and the borrowAmount.\\n * On success, the vToken borrowAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(borrower, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call _doTransferIn for the payer and the repayAmount\\n * On success, the vToken holds an additional repayAmount of cash.\\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == NO_ERROR, \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetInterestRateModelFreshCheck();\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n }\\n\\n /**\\n * Safe Token **\\n */\\n\\n /**\\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\\n * This function returns the actual amount received,\\n * which may be less than `amount` if there is a fee attached to the transfer.\\n * @param from Sender of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n * @return Actual amount received\\n */\\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n // Return the amount that was *actually* transferred\\n return balanceAfter - balanceBefore;\\n }\\n\\n /**\\n * @dev Just a regular ERC-20 transfer, reverts on failure\\n * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n _setComptroller(comptroller_);\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = _getBlockNumber();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying tokens owned by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n * @return Current block number\\n */\\n function _getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xf4f49f4a1718a36a7cbd413e959d957eade62d4ad96c0ebde4562e53cac72f7e\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\n\\n // Maximum borrow rate that can ever be applied (.0005% / block)\\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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[48] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves block delta is changed\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x777842977e2441dd79f4781ff61f431dda351c3d33862e40063ef58d03b489a1\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x909eb76841ebd57d8f53686b76b1a09da7bbbbcddb29510c41674d5aa84c713e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b612e7f80620000f36000396000f3fe608060405234801561001057600080fd5b50600436106102065760003560e01c806379ba50971161011a578063be203094116100ad578063db7954fd1161007c578063db7954fd14610537578063e30c39781461054a578063efc75f241461055b578063f2fde38b1461057c578063f7c618c11461058f57600080fd5b8063be203094146104e7578063be26317e146104fa578063bea6b8b814610503578063ca37271b1461052457600080fd5b80638c37dfa3116100e95780638c37dfa31461045b5780638da5cb5b1461046e57806392a1823514610493578063b4a0bdf3146104d657600080fd5b806379ba50971461040d5780637c05a7c51461041557806380d45a2d14610435578063856e5e6c1461044857600080fd5b80632eed69061161019d5780636d0493291161016c5780636d049329146103935780636dfd08ca146103a6578063715018a6146103d2578063741b2525146103da57806374c4c1cc146103ed57600080fd5b80632eed69061461033c57806342cbb15c1461034f578063552c0971146103555780636a95ddef1461038057600080fd5b80631627ee89116101d95780631627ee891461027857806323526079146102a65780632a869a4d146102b95780632c427b57146102cc57600080fd5b806304caeb101461020b5780630a3a3a9e146102205780630e32cb8614610233578063160c3a0314610246575b600080fd5b61021e610219366004612660565b6105a3565b005b61021e61022e3660046126b0565b610786565b61021e6102413660046126b0565b6107bd565b61025b6a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020015b60405180910390f35b6102986102863660046126b0565b60fd6020526000908152604090205481565b60405190815260200161026f565b61021e6102b436600461270f565b6107ce565b61021e6102c73660046126b0565b610807565b6103106102da3660046126b0565b61010060205260009081526040902080546001909101546001600160e01b0382169163ffffffff600160e01b9091048116911683565b604080516001600160e01b03909416845263ffffffff928316602085015291169082015260600161026f565b61021e61034a366004612745565b610961565b43610298565b610298610363366004612771565b60fc60209081526000928352604080842090915290825290205481565b61021e61038e3660046127aa565b610a0f565b61021e6103a1366004612745565b610a4a565b6102986103b4366004612771565b61010360209081526000928352604080842090915290825290205481565b61021e610b01565b61021e6103e83660046126b0565b610b15565b6102986103fb3660046126b0565b60ff6020526000908152604090205481565b61021e610c02565b6102986104233660046126b0565b60fe6020526000908152604090205481565b61021e6104433660046127f2565b610c79565b61021e610456366004612857565b610c8a565b61021e61046936600461294c565b610dc6565b6033546001600160a01b03165b6040516001600160a01b03909116815260200161026f565b6103106104a13660046126b0565b60fb60205260009081526040902080546001909101546001600160e01b0382169163ffffffff600160e01b9091048116911683565b6097546001600160a01b031661047b565b61021e6104f53660046129d4565b610ebd565b61029860c95481565b6102986105113660046126b0565b6101026020526000908152604090205481565b61021e6105323660046126b0565b611015565b61021e610545366004612771565b611095565b6065546001600160a01b031661047b565b6102986105693660046126b0565b6101016020526000908152604090205481565b61021e61058a3660046126b0565b6110ca565b6101055461047b906001600160a01b031681565b80516105ae8161113b565b60005b818110156107405760008382815181106105cd576105cd612a27565b602090810291909101015161010454604051633d98a1e560e01b81526001600160a01b038084166004830152929350911690633d98a1e590602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612a3d565b6106925760405162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b60448201526064015b60405180910390fd5b60006040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107019190612a5f565b9052905061070f828261116c565b61071a828783611394565b61072382611523565b61072d8287611706565b50508061073990612a8e565b90506105b1565b506001600160a01b038316600090815260fd60205260409020546107659084906118ab565b6001600160a01b03909316600090815260fd60205260409020929092555050565b610104546001600160a01b031633146107b15760405162461bcd60e51b815260040161068990612aa7565b6107ba81611523565b50565b6107c5611961565b6107ba816119bb565b610104546001600160a01b031633146107f95760405162461bcd60e51b815260040161068990612aa7565b610803828261116c565b5050565b610104546001600160a01b031633146108325760405162461bcd60e51b815260040161068990612aa7565b6000610874435b6040518060400160405280601c81526020017f626c6f636b206e756d6265722065786365656473203332206269747300000000815250611a81565b6001600160a01b038316600090815260fb6020908152604080832061010090925282208154939450909290916001600160e01b0390911690036108d05781546001600160e01b0319166a0c097ce7bc90715b34b9f160241b1782555b80546001600160e01b03166000036109015780546001600160e01b0319166a0c097ce7bc90715b34b9f160241b1781555b805463ffffffff8416600160e01b026001600160e01b039182168117835583549091161782556040516001600160a01b038516907ffe6944646a362be70b0925ea999b3d9f755589a63ffcd89e4fb2b0affd252c7190600090a250505050565b610969611961565b61097282610b15565b80600003610999576001600160a01b038216600090815261010260205260408120556109b5565b436001600160a01b038316600090815261010260205260409020555b6001600160a01b0382166000818152610101602052604090819020839055517f4882c0217331870166b5d239c9f7be7801bab4be26560cd2f8789145d0fd3af490610a039084815260200190565b60405180910390a25050565b610104546001600160a01b03163314610a3a5760405162461bcd60e51b815260040161068990612aa7565b610a45838383611394565b505050565b610a52611961565b6000610a5e83836118ab565b90508015610ab95760405162461bcd60e51b815260206004820152602260248201527f696e73756666696369656e7420726577617264546f6b656e20666f72206772616044820152611b9d60f21b6064820152608401610689565b826001600160a01b03167f251909abf904fc80eac3f0d4c25e5c800441ea19fda63c6f0df08e4f24f926f983604051610af491815260200190565b60405180910390a2505050565b610b09611961565b610b136000611ab1565b565b6001600160a01b0381166000908152610101602090815260408083205461010290925282205490914391610b4a908390611aca565b9050600081118015610b5c5750600083115b15610bfc576000610b6d8285611add565b6001600160a01b038616600090815260fd602052604081205491925090610b949083611ae9565b6001600160a01b038716600081815260fd602081815260408084208681556101028352938190208a90559181529154905190815292935090917f38fe05baf9dc12e4e3bfda3daba26419e9930bf26ee6227f407ca46f8c9c29bc91015b60405180910390a250505b50505050565b60655433906001600160a01b03168114610c705760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610689565b6107ba81611ab1565b610c81611961565b6107ba81611af5565b610cab604051806060016040528060328152602001612de560329139611b8f565b848381148015610cba57508082145b610d2c5760405162461bcd60e51b815260206004820152603860248201527f526577617264734469737472696275746f723a3a7365744c617374526577617260448201527f64696e67426c6f636b7320696e76616c696420696e70757400000000000000006064820152608401610689565b60005b81811015610dbc57610db4888883818110610d4c57610d4c612a27565b9050602002016020810190610d6191906126b0565b878784818110610d7357610d73612a27565b9050602002016020810190610d889190612aee565b868685818110610d9a57610d9a612a27565b9050602002016020810190610daf9190612aee565b611c29565b600101610d2f565b5050505050505050565b610de7604051806060016040528060338152602001612e1760339139611b8f565b8251825181148015610df95750815181145b610e455760405162461bcd60e51b815260206004820152601c60248201527f696e76616c696420736574526577617264546f6b656e537065656473000000006044820152606401610689565b60005b81811015610eb657610ea6858281518110610e6557610e65612a27565b6020026020010151858381518110610e7f57610e7f612a27565b6020026020010151858481518110610e9957610e99612a27565b6020026020010151611ebf565b610eaf81612a8e565b9050610e48565b5050505050565b600054610100900460ff1615808015610edd5750600054600160ff909116105b80610ef75750303b158015610ef7575060005460ff166001145b610f5a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610689565b6000805460ff191660011790558015610f7d576000805461ff0019166101001790555b61010480546001600160a01b038088166001600160a01b031992831617909255610105805492871692909116919091179055610fb76120ef565b610fc08261211e565b610fc983611af5565b8015610eb6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6107ba8161010460009054906101000a90046001600160a01b03166001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561106d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102199190810190612b14565b610104546001600160a01b031633146110c05760405162461bcd60e51b815260040161068990612aa7565b6108038282611706565b6110d2611961565b606580546001600160a01b0383166001600160a01b031990911681179091556111036033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60c9548111156107ba5760c95460405163792bfb1b60e11b8152600481019190915260248101829052604401610689565b6001600160a01b03821660009081526101006020908152604080832060fe909252822054909161119b43610839565b600184015490915063ffffffff16158015906111c45750600183015463ffffffff908116908216115b156111d65750600182015463ffffffff165b82546000906111f59063ffffffff80851691600160e01b900416611aca565b90506000811180156112075750600083115b15611336576000611279876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561124f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112739190612a5f565b87612145565b905060006112878386611add565b905060008083116112a757604051806020016040528060008152506112b1565b6112b18284612163565b604080516020810190915288546001600160e01b03168152909150611314906112da90836121a7565b5160408051808201909152601a81527f6e657720696e646578206578636565647320323234206269747300000000000060208201526121d3565b6001600160e01b0316600160e01b63ffffffff87160217875550611358915050565b80156113585783546001600160e01b0316600160e01b63ffffffff8416021784555b856001600160a01b03167fbfeed4eb85c013b0e466fdfdbaa785159ff7986078247dc95f1c717a5bd6bca286604051610bf19151815260200190565b6001600160a01b038381166000908152610100602090815260408083208054610103845282852095881685529490925290912080546001600160e01b03909316908190559091801580156113f657506a0c097ce7bc90715b34b9f160241b8210155b1561140c57506a0c097ce7bc90715b34b9f160241b5b600060405180602001604052806114238585611aca565b90526040516395dd919360e01b81526001600160a01b03888116600483015291925060009161147691908a16906395dd919390602401602060405180830381865afa15801561124f573d6000803e3d6000fd5b90508015610dbc57600061148a82846121fe565b6001600160a01b038916600090815260fd6020526040812054919250906114b19083611ae9565b6001600160a01b038a8116600081815260fd602090815260409182902085905581518781529081018590529081018a905292935091908c16907f510d7612da9ca257889eabdfbe0366aaea10020be46f7810f4afb2111d80aa939060600160405180910390a350505050505050505050565b6001600160a01b038116600090815260fb6020908152604080832060ff909252822054909161155143610839565b600184015490915063ffffffff161580159061157a5750600183015463ffffffff908116908216115b1561158c5750600182015463ffffffff165b82546000906115ab9063ffffffff80851691600160e01b900416611aca565b90506000811180156115bd5750600083115b156116a9576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611602573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116269190612a5f565b905060006116348386611add565b90506000808311611654576040518060200160405280600081525061165e565b61165e8284612163565b604080516020810190915288546001600160e01b03168152909150611687906112da90836121a7565b6001600160e01b0316600160e01b63ffffffff871602178755506116cb915050565b80156116cb5783546001600160e01b0316600160e01b63ffffffff8416021784555b6040516001600160a01b038616907f6a7b996800070d8bc0f9a3ddcb0a4b09bc1653f76381d745444956366afd423a90600090a25050505050565b6001600160a01b03828116600090815260fb60209081526040808320805460fc845282852095871685529490925290912080546001600160e01b039093169081905590918015801561176657506a0c097ce7bc90715b34b9f160241b8210155b1561177c57506a0c097ce7bc90715b34b9f160241b5b600060405180602001604052806117938585611aca565b90526040516370a0823160e01b81526001600160a01b0387811660048301529192506000918816906370a0823190602401602060405180830381865afa1580156117e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118059190612a5f565b9050600061181382846121fe565b6001600160a01b038816600090815260fd60205260408120549192509061183a9083611ae9565b6001600160a01b03898116600081815260fd602090815260409182902085905581518781529081018590529081018a905292935091908b16907f9563ff6035b973f2e4514ad9315010c220eb74b0c33a782a18118a199a97e4429060600160405180910390a3505050505050505050565b610105546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156118f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191d9190612a5f565b905060008311801561192f5750808311155b15611956576101055461194c906001600160a01b03168585612227565b600091505061195b565b829150505b92915050565b6033546001600160a01b03163314610b135760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610689565b6001600160a01b038116611a1f5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610689565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091015b60405180910390a15050565b60008163ffffffff841115611aa95760405162461bcd60e51b81526004016106899190612bfb565b509192915050565b606580546001600160a01b03191690556107ba81612279565b6000611ad68284612c0e565b9392505050565b6000611ad68284612c25565b6000611ad68284612c44565b60c9548111611b515760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610689565b60c980549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611a75565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab90611bc29033908690600401612c5c565b602060405180830381865afa158015611bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c039190612a3d565b90508061080357333083604051634a3fa29360e01b815260040161068993929190612c80565b61010454604051633d98a1e560e01b81526001600160a01b03858116600483015290911690633d98a1e590602401602060405180830381865afa158015611c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c989190612a3d565b611ce45760405162461bcd60e51b815260206004820181905260248201527f726577617264546f6b656e206d61726b6574206973206e6f74206c69737465646044820152606401610689565b4363ffffffff83168110611d0a5760405162461bcd60e51b815260040161068990612cb5565b808263ffffffff1611611d2f5760405162461bcd60e51b815260040161068990612cb5565b6001600160a01b038416600090815260fb6020908152604080832060019081015461010090935292209091015463ffffffff9182169116811580611d785750828263ffffffff16115b611d945760405162461bcd60e51b815260040161068990612d12565b63ffffffff81161580611dac5750828163ffffffff16115b611dc85760405162461bcd60e51b815260040161068990612d12565b8463ffffffff168263ffffffff1614611e41576001600160a01b038616600081815260fb6020908152604091829020600101805463ffffffff191663ffffffff8a1690811790915591519182527f41b697bf2627e0a03f253382759baaab2469897004cc619465a3d8f4bb6b3fec910160405180910390a25b8363ffffffff168163ffffffff1614611eb7576001600160a01b03861660008181526101006020908152604091829020600101805463ffffffff191663ffffffff891690811790915591519182527f4163eb203170b7facecc8d7307e3f8affa8826d4df30fc722f8f8ce17988eb919101610bf1565b505050505050565b61010454604051633d98a1e560e01b81526001600160a01b03858116600483015290911690633d98a1e590602401602060405180830381865afa158015611f0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2e9190612a3d565b611f7a5760405162461bcd60e51b815260206004820181905260248201527f726577617264546f6b656e206d61726b6574206973206e6f74206c69737465646044820152606401610689565b6001600160a01b038316600090815260ff60205260409020548214611ff857611fa283611523565b6001600160a01b038316600081815260ff602052604090819020849055517f24741480445e83baea9eb28086e16a4377ebb4f003c773e386496fd90b3ed04e90611fef9085815260200190565b60405180910390a25b6001600160a01b038316600090815260fe60205260409020548114610a455760006040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612062573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120869190612a5f565b90529050612094848261116c565b6001600160a01b038416600081815260fe602052604090819020849055517f2091432bbf4aa40f4785b469e931d32c5f5c6ba66dcf702a99cbe776df729c3c906120e19085815260200190565b60405180910390a250505050565b600054610100900460ff166121165760405162461bcd60e51b815260040161068990612d5b565b610b136122cb565b600054610100900460ff166107c55760405162461bcd60e51b815260040161068990612d5b565b6000611ad661215c84670de0b6b3a7640000611add565b83516122fb565b604080516020810190915260008152604051806020016040528061219e612198866a0c097ce7bc90715b34b9f160241b611add565b856122fb565b90529392505050565b604080516020810190915260008152604051806020016040528061219e85600001518560000151611ae9565b6000816001600160e01b03841115611aa95760405162461bcd60e51b81526004016106899190612bfb565b60006a0c097ce7bc90715b34b9f160241b61221d848460000151611add565b611ad69190612da6565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610a45908490612307565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166122f25760405162461bcd60e51b815260040161068990612d5b565b610b1333611ab1565b6000611ad68284612da6565b600061235c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123dc9092919063ffffffff16565b905080516000148061237d57508080602001905181019061237d9190612a3d565b610a455760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610689565b60606123eb84846000856123f3565b949350505050565b6060824710156124545760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610689565b600080866001600160a01b031685876040516124709190612dc8565b60006040518083038185875af1925050503d80600081146124ad576040519150601f19603f3d011682016040523d82523d6000602084013e6124b2565b606091505b50915091506124c3878383876124ce565b979650505050505050565b6060831561253d578251600003612536576001600160a01b0385163b6125365760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610689565b50816123eb565b6123eb83838151156125525781518083602001fd5b8060405162461bcd60e51b81526004016106899190612bfb565b6001600160a01b03811681146107ba57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156125c0576125c0612581565b604052919050565b600067ffffffffffffffff8211156125e2576125e2612581565b5060051b60200190565b600082601f8301126125fd57600080fd5b8135602061261261260d836125c8565b612597565b82815260059290921b8401810191818101908684111561263157600080fd5b8286015b848110156126555780356126488161256c565b8352918301918301612635565b509695505050505050565b6000806040838503121561267357600080fd5b823561267e8161256c565b9150602083013567ffffffffffffffff81111561269a57600080fd5b6126a6858286016125ec565b9150509250929050565b6000602082840312156126c257600080fd5b8135611ad68161256c565b6000602082840312156126df57600080fd5b6040516020810181811067ffffffffffffffff8211171561270257612702612581565b6040529135825250919050565b6000806040838503121561272257600080fd5b823561272d8161256c565b915061273c84602085016126cd565b90509250929050565b6000806040838503121561275857600080fd5b82356127638161256c565b946020939093013593505050565b6000806040838503121561278457600080fd5b823561278f8161256c565b9150602083013561279f8161256c565b809150509250929050565b6000806000606084860312156127bf57600080fd5b83356127ca8161256c565b925060208401356127da8161256c565b91506127e985604086016126cd565b90509250925092565b60006020828403121561280457600080fd5b5035919050565b60008083601f84011261281d57600080fd5b50813567ffffffffffffffff81111561283557600080fd5b6020830191508360208260051b850101111561285057600080fd5b9250929050565b6000806000806000806060878903121561287057600080fd5b863567ffffffffffffffff8082111561288857600080fd5b6128948a838b0161280b565b909850965060208901359150808211156128ad57600080fd5b6128b98a838b0161280b565b909650945060408901359150808211156128d257600080fd5b506128df89828a0161280b565b979a9699509497509295939492505050565b600082601f83011261290257600080fd5b8135602061291261260d836125c8565b82815260059290921b8401810191818101908684111561293157600080fd5b8286015b848110156126555780358352918301918301612935565b60008060006060848603121561296157600080fd5b833567ffffffffffffffff8082111561297957600080fd5b612985878388016125ec565b9450602086013591508082111561299b57600080fd5b6129a7878388016128f1565b935060408601359150808211156129bd57600080fd5b506129ca868287016128f1565b9150509250925092565b600080600080608085870312156129ea57600080fd5b84356129f58161256c565b93506020850135612a058161256c565b9250604085013591506060850135612a1c8161256c565b939692955090935050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a4f57600080fd5b81518015158114611ad657600080fd5b600060208284031215612a7157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600060018201612aa057612aa0612a78565b5060010190565b60208082526027908201527f4f6e6c7920636f6d7074726f6c6c65722063616e2063616c6c207468697320666040820152663ab731ba34b7b760c91b606082015260800190565b600060208284031215612b0057600080fd5b813563ffffffff81168114611ad657600080fd5b60006020808385031215612b2757600080fd5b825167ffffffffffffffff811115612b3e57600080fd5b8301601f81018513612b4f57600080fd5b8051612b5d61260d826125c8565b81815260059190911b82018301908381019087831115612b7c57600080fd5b928401925b828410156124c3578351612b948161256c565b82529284019290840190612b81565b60005b83811015612bbe578181015183820152602001612ba6565b83811115610bfc5750506000910152565b60008151808452612be7816020860160208601612ba3565b601f01601f19169290920160200192915050565b602081526000611ad66020830184612bcf565b600082821015612c2057612c20612a78565b500390565b6000816000190483118215151615612c3f57612c3f612a78565b500290565b60008219821115612c5757612c57612a78565b500190565b6001600160a01b03831681526040602082018190526000906123eb90830184612bcf565b6001600160a01b03848116825283166020820152606060408201819052600090612cac90830184612bcf565b95945050505050565b60208082526037908201527f73657474696e67206c61737420726577617264696e6720626c6f636b20696e2060408201527f7468652070617374206973206e6f7420616c6c6f776564000000000000000000606082015260800190565b60208082526029908201527f7468697320526577617264734469737472696275746f7220697320616c726561604082015268191e481b1bd8dad95960ba1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600082612dc357634e487b7160e01b600052601260045260246000fd5b500490565b60008251612dda818460208701612ba3565b919091019291505056fe7365744c617374526577617264696e67426c6f636b28616464726573735b5d2c75696e7433325b5d2c75696e7433325b5d29736574526577617264546f6b656e53706565647328616464726573735b5d2c75696e743235365b5d2c75696e743235365b5d29a26469706673582212201474ed00ed7ce8b69f43bc3d1d7d04eb0339bf5ee87fbdf788b3116098a88cef64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102065760003560e01c806379ba50971161011a578063be203094116100ad578063db7954fd1161007c578063db7954fd14610537578063e30c39781461054a578063efc75f241461055b578063f2fde38b1461057c578063f7c618c11461058f57600080fd5b8063be203094146104e7578063be26317e146104fa578063bea6b8b814610503578063ca37271b1461052457600080fd5b80638c37dfa3116100e95780638c37dfa31461045b5780638da5cb5b1461046e57806392a1823514610493578063b4a0bdf3146104d657600080fd5b806379ba50971461040d5780637c05a7c51461041557806380d45a2d14610435578063856e5e6c1461044857600080fd5b80632eed69061161019d5780636d0493291161016c5780636d049329146103935780636dfd08ca146103a6578063715018a6146103d2578063741b2525146103da57806374c4c1cc146103ed57600080fd5b80632eed69061461033c57806342cbb15c1461034f578063552c0971146103555780636a95ddef1461038057600080fd5b80631627ee89116101d95780631627ee891461027857806323526079146102a65780632a869a4d146102b95780632c427b57146102cc57600080fd5b806304caeb101461020b5780630a3a3a9e146102205780630e32cb8614610233578063160c3a0314610246575b600080fd5b61021e610219366004612660565b6105a3565b005b61021e61022e3660046126b0565b610786565b61021e6102413660046126b0565b6107bd565b61025b6a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020015b60405180910390f35b6102986102863660046126b0565b60fd6020526000908152604090205481565b60405190815260200161026f565b61021e6102b436600461270f565b6107ce565b61021e6102c73660046126b0565b610807565b6103106102da3660046126b0565b61010060205260009081526040902080546001909101546001600160e01b0382169163ffffffff600160e01b9091048116911683565b604080516001600160e01b03909416845263ffffffff928316602085015291169082015260600161026f565b61021e61034a366004612745565b610961565b43610298565b610298610363366004612771565b60fc60209081526000928352604080842090915290825290205481565b61021e61038e3660046127aa565b610a0f565b61021e6103a1366004612745565b610a4a565b6102986103b4366004612771565b61010360209081526000928352604080842090915290825290205481565b61021e610b01565b61021e6103e83660046126b0565b610b15565b6102986103fb3660046126b0565b60ff6020526000908152604090205481565b61021e610c02565b6102986104233660046126b0565b60fe6020526000908152604090205481565b61021e6104433660046127f2565b610c79565b61021e610456366004612857565b610c8a565b61021e61046936600461294c565b610dc6565b6033546001600160a01b03165b6040516001600160a01b03909116815260200161026f565b6103106104a13660046126b0565b60fb60205260009081526040902080546001909101546001600160e01b0382169163ffffffff600160e01b9091048116911683565b6097546001600160a01b031661047b565b61021e6104f53660046129d4565b610ebd565b61029860c95481565b6102986105113660046126b0565b6101026020526000908152604090205481565b61021e6105323660046126b0565b611015565b61021e610545366004612771565b611095565b6065546001600160a01b031661047b565b6102986105693660046126b0565b6101016020526000908152604090205481565b61021e61058a3660046126b0565b6110ca565b6101055461047b906001600160a01b031681565b80516105ae8161113b565b60005b818110156107405760008382815181106105cd576105cd612a27565b602090810291909101015161010454604051633d98a1e560e01b81526001600160a01b038084166004830152929350911690633d98a1e590602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612a3d565b6106925760405162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b60448201526064015b60405180910390fd5b60006040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107019190612a5f565b9052905061070f828261116c565b61071a828783611394565b61072382611523565b61072d8287611706565b50508061073990612a8e565b90506105b1565b506001600160a01b038316600090815260fd60205260409020546107659084906118ab565b6001600160a01b03909316600090815260fd60205260409020929092555050565b610104546001600160a01b031633146107b15760405162461bcd60e51b815260040161068990612aa7565b6107ba81611523565b50565b6107c5611961565b6107ba816119bb565b610104546001600160a01b031633146107f95760405162461bcd60e51b815260040161068990612aa7565b610803828261116c565b5050565b610104546001600160a01b031633146108325760405162461bcd60e51b815260040161068990612aa7565b6000610874435b6040518060400160405280601c81526020017f626c6f636b206e756d6265722065786365656473203332206269747300000000815250611a81565b6001600160a01b038316600090815260fb6020908152604080832061010090925282208154939450909290916001600160e01b0390911690036108d05781546001600160e01b0319166a0c097ce7bc90715b34b9f160241b1782555b80546001600160e01b03166000036109015780546001600160e01b0319166a0c097ce7bc90715b34b9f160241b1781555b805463ffffffff8416600160e01b026001600160e01b039182168117835583549091161782556040516001600160a01b038516907ffe6944646a362be70b0925ea999b3d9f755589a63ffcd89e4fb2b0affd252c7190600090a250505050565b610969611961565b61097282610b15565b80600003610999576001600160a01b038216600090815261010260205260408120556109b5565b436001600160a01b038316600090815261010260205260409020555b6001600160a01b0382166000818152610101602052604090819020839055517f4882c0217331870166b5d239c9f7be7801bab4be26560cd2f8789145d0fd3af490610a039084815260200190565b60405180910390a25050565b610104546001600160a01b03163314610a3a5760405162461bcd60e51b815260040161068990612aa7565b610a45838383611394565b505050565b610a52611961565b6000610a5e83836118ab565b90508015610ab95760405162461bcd60e51b815260206004820152602260248201527f696e73756666696369656e7420726577617264546f6b656e20666f72206772616044820152611b9d60f21b6064820152608401610689565b826001600160a01b03167f251909abf904fc80eac3f0d4c25e5c800441ea19fda63c6f0df08e4f24f926f983604051610af491815260200190565b60405180910390a2505050565b610b09611961565b610b136000611ab1565b565b6001600160a01b0381166000908152610101602090815260408083205461010290925282205490914391610b4a908390611aca565b9050600081118015610b5c5750600083115b15610bfc576000610b6d8285611add565b6001600160a01b038616600090815260fd602052604081205491925090610b949083611ae9565b6001600160a01b038716600081815260fd602081815260408084208681556101028352938190208a90559181529154905190815292935090917f38fe05baf9dc12e4e3bfda3daba26419e9930bf26ee6227f407ca46f8c9c29bc91015b60405180910390a250505b50505050565b60655433906001600160a01b03168114610c705760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610689565b6107ba81611ab1565b610c81611961565b6107ba81611af5565b610cab604051806060016040528060328152602001612de560329139611b8f565b848381148015610cba57508082145b610d2c5760405162461bcd60e51b815260206004820152603860248201527f526577617264734469737472696275746f723a3a7365744c617374526577617260448201527f64696e67426c6f636b7320696e76616c696420696e70757400000000000000006064820152608401610689565b60005b81811015610dbc57610db4888883818110610d4c57610d4c612a27565b9050602002016020810190610d6191906126b0565b878784818110610d7357610d73612a27565b9050602002016020810190610d889190612aee565b868685818110610d9a57610d9a612a27565b9050602002016020810190610daf9190612aee565b611c29565b600101610d2f565b5050505050505050565b610de7604051806060016040528060338152602001612e1760339139611b8f565b8251825181148015610df95750815181145b610e455760405162461bcd60e51b815260206004820152601c60248201527f696e76616c696420736574526577617264546f6b656e537065656473000000006044820152606401610689565b60005b81811015610eb657610ea6858281518110610e6557610e65612a27565b6020026020010151858381518110610e7f57610e7f612a27565b6020026020010151858481518110610e9957610e99612a27565b6020026020010151611ebf565b610eaf81612a8e565b9050610e48565b5050505050565b600054610100900460ff1615808015610edd5750600054600160ff909116105b80610ef75750303b158015610ef7575060005460ff166001145b610f5a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610689565b6000805460ff191660011790558015610f7d576000805461ff0019166101001790555b61010480546001600160a01b038088166001600160a01b031992831617909255610105805492871692909116919091179055610fb76120ef565b610fc08261211e565b610fc983611af5565b8015610eb6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6107ba8161010460009054906101000a90046001600160a01b03166001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561106d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102199190810190612b14565b610104546001600160a01b031633146110c05760405162461bcd60e51b815260040161068990612aa7565b6108038282611706565b6110d2611961565b606580546001600160a01b0383166001600160a01b031990911681179091556111036033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60c9548111156107ba5760c95460405163792bfb1b60e11b8152600481019190915260248101829052604401610689565b6001600160a01b03821660009081526101006020908152604080832060fe909252822054909161119b43610839565b600184015490915063ffffffff16158015906111c45750600183015463ffffffff908116908216115b156111d65750600182015463ffffffff165b82546000906111f59063ffffffff80851691600160e01b900416611aca565b90506000811180156112075750600083115b15611336576000611279876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561124f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112739190612a5f565b87612145565b905060006112878386611add565b905060008083116112a757604051806020016040528060008152506112b1565b6112b18284612163565b604080516020810190915288546001600160e01b03168152909150611314906112da90836121a7565b5160408051808201909152601a81527f6e657720696e646578206578636565647320323234206269747300000000000060208201526121d3565b6001600160e01b0316600160e01b63ffffffff87160217875550611358915050565b80156113585783546001600160e01b0316600160e01b63ffffffff8416021784555b856001600160a01b03167fbfeed4eb85c013b0e466fdfdbaa785159ff7986078247dc95f1c717a5bd6bca286604051610bf19151815260200190565b6001600160a01b038381166000908152610100602090815260408083208054610103845282852095881685529490925290912080546001600160e01b03909316908190559091801580156113f657506a0c097ce7bc90715b34b9f160241b8210155b1561140c57506a0c097ce7bc90715b34b9f160241b5b600060405180602001604052806114238585611aca565b90526040516395dd919360e01b81526001600160a01b03888116600483015291925060009161147691908a16906395dd919390602401602060405180830381865afa15801561124f573d6000803e3d6000fd5b90508015610dbc57600061148a82846121fe565b6001600160a01b038916600090815260fd6020526040812054919250906114b19083611ae9565b6001600160a01b038a8116600081815260fd602090815260409182902085905581518781529081018590529081018a905292935091908c16907f510d7612da9ca257889eabdfbe0366aaea10020be46f7810f4afb2111d80aa939060600160405180910390a350505050505050505050565b6001600160a01b038116600090815260fb6020908152604080832060ff909252822054909161155143610839565b600184015490915063ffffffff161580159061157a5750600183015463ffffffff908116908216115b1561158c5750600182015463ffffffff165b82546000906115ab9063ffffffff80851691600160e01b900416611aca565b90506000811180156115bd5750600083115b156116a9576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611602573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116269190612a5f565b905060006116348386611add565b90506000808311611654576040518060200160405280600081525061165e565b61165e8284612163565b604080516020810190915288546001600160e01b03168152909150611687906112da90836121a7565b6001600160e01b0316600160e01b63ffffffff871602178755506116cb915050565b80156116cb5783546001600160e01b0316600160e01b63ffffffff8416021784555b6040516001600160a01b038616907f6a7b996800070d8bc0f9a3ddcb0a4b09bc1653f76381d745444956366afd423a90600090a25050505050565b6001600160a01b03828116600090815260fb60209081526040808320805460fc845282852095871685529490925290912080546001600160e01b039093169081905590918015801561176657506a0c097ce7bc90715b34b9f160241b8210155b1561177c57506a0c097ce7bc90715b34b9f160241b5b600060405180602001604052806117938585611aca565b90526040516370a0823160e01b81526001600160a01b0387811660048301529192506000918816906370a0823190602401602060405180830381865afa1580156117e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118059190612a5f565b9050600061181382846121fe565b6001600160a01b038816600090815260fd60205260408120549192509061183a9083611ae9565b6001600160a01b03898116600081815260fd602090815260409182902085905581518781529081018590529081018a905292935091908b16907f9563ff6035b973f2e4514ad9315010c220eb74b0c33a782a18118a199a97e4429060600160405180910390a3505050505050505050565b610105546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156118f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191d9190612a5f565b905060008311801561192f5750808311155b15611956576101055461194c906001600160a01b03168585612227565b600091505061195b565b829150505b92915050565b6033546001600160a01b03163314610b135760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610689565b6001600160a01b038116611a1f5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610689565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091015b60405180910390a15050565b60008163ffffffff841115611aa95760405162461bcd60e51b81526004016106899190612bfb565b509192915050565b606580546001600160a01b03191690556107ba81612279565b6000611ad68284612c0e565b9392505050565b6000611ad68284612c25565b6000611ad68284612c44565b60c9548111611b515760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610689565b60c980549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611a75565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab90611bc29033908690600401612c5c565b602060405180830381865afa158015611bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c039190612a3d565b90508061080357333083604051634a3fa29360e01b815260040161068993929190612c80565b61010454604051633d98a1e560e01b81526001600160a01b03858116600483015290911690633d98a1e590602401602060405180830381865afa158015611c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c989190612a3d565b611ce45760405162461bcd60e51b815260206004820181905260248201527f726577617264546f6b656e206d61726b6574206973206e6f74206c69737465646044820152606401610689565b4363ffffffff83168110611d0a5760405162461bcd60e51b815260040161068990612cb5565b808263ffffffff1611611d2f5760405162461bcd60e51b815260040161068990612cb5565b6001600160a01b038416600090815260fb6020908152604080832060019081015461010090935292209091015463ffffffff9182169116811580611d785750828263ffffffff16115b611d945760405162461bcd60e51b815260040161068990612d12565b63ffffffff81161580611dac5750828163ffffffff16115b611dc85760405162461bcd60e51b815260040161068990612d12565b8463ffffffff168263ffffffff1614611e41576001600160a01b038616600081815260fb6020908152604091829020600101805463ffffffff191663ffffffff8a1690811790915591519182527f41b697bf2627e0a03f253382759baaab2469897004cc619465a3d8f4bb6b3fec910160405180910390a25b8363ffffffff168163ffffffff1614611eb7576001600160a01b03861660008181526101006020908152604091829020600101805463ffffffff191663ffffffff891690811790915591519182527f4163eb203170b7facecc8d7307e3f8affa8826d4df30fc722f8f8ce17988eb919101610bf1565b505050505050565b61010454604051633d98a1e560e01b81526001600160a01b03858116600483015290911690633d98a1e590602401602060405180830381865afa158015611f0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2e9190612a3d565b611f7a5760405162461bcd60e51b815260206004820181905260248201527f726577617264546f6b656e206d61726b6574206973206e6f74206c69737465646044820152606401610689565b6001600160a01b038316600090815260ff60205260409020548214611ff857611fa283611523565b6001600160a01b038316600081815260ff602052604090819020849055517f24741480445e83baea9eb28086e16a4377ebb4f003c773e386496fd90b3ed04e90611fef9085815260200190565b60405180910390a25b6001600160a01b038316600090815260fe60205260409020548114610a455760006040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612062573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120869190612a5f565b90529050612094848261116c565b6001600160a01b038416600081815260fe602052604090819020849055517f2091432bbf4aa40f4785b469e931d32c5f5c6ba66dcf702a99cbe776df729c3c906120e19085815260200190565b60405180910390a250505050565b600054610100900460ff166121165760405162461bcd60e51b815260040161068990612d5b565b610b136122cb565b600054610100900460ff166107c55760405162461bcd60e51b815260040161068990612d5b565b6000611ad661215c84670de0b6b3a7640000611add565b83516122fb565b604080516020810190915260008152604051806020016040528061219e612198866a0c097ce7bc90715b34b9f160241b611add565b856122fb565b90529392505050565b604080516020810190915260008152604051806020016040528061219e85600001518560000151611ae9565b6000816001600160e01b03841115611aa95760405162461bcd60e51b81526004016106899190612bfb565b60006a0c097ce7bc90715b34b9f160241b61221d848460000151611add565b611ad69190612da6565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610a45908490612307565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166122f25760405162461bcd60e51b815260040161068990612d5b565b610b1333611ab1565b6000611ad68284612da6565b600061235c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123dc9092919063ffffffff16565b905080516000148061237d57508080602001905181019061237d9190612a3d565b610a455760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610689565b60606123eb84846000856123f3565b949350505050565b6060824710156124545760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610689565b600080866001600160a01b031685876040516124709190612dc8565b60006040518083038185875af1925050503d80600081146124ad576040519150601f19603f3d011682016040523d82523d6000602084013e6124b2565b606091505b50915091506124c3878383876124ce565b979650505050505050565b6060831561253d578251600003612536576001600160a01b0385163b6125365760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610689565b50816123eb565b6123eb83838151156125525781518083602001fd5b8060405162461bcd60e51b81526004016106899190612bfb565b6001600160a01b03811681146107ba57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156125c0576125c0612581565b604052919050565b600067ffffffffffffffff8211156125e2576125e2612581565b5060051b60200190565b600082601f8301126125fd57600080fd5b8135602061261261260d836125c8565b612597565b82815260059290921b8401810191818101908684111561263157600080fd5b8286015b848110156126555780356126488161256c565b8352918301918301612635565b509695505050505050565b6000806040838503121561267357600080fd5b823561267e8161256c565b9150602083013567ffffffffffffffff81111561269a57600080fd5b6126a6858286016125ec565b9150509250929050565b6000602082840312156126c257600080fd5b8135611ad68161256c565b6000602082840312156126df57600080fd5b6040516020810181811067ffffffffffffffff8211171561270257612702612581565b6040529135825250919050565b6000806040838503121561272257600080fd5b823561272d8161256c565b915061273c84602085016126cd565b90509250929050565b6000806040838503121561275857600080fd5b82356127638161256c565b946020939093013593505050565b6000806040838503121561278457600080fd5b823561278f8161256c565b9150602083013561279f8161256c565b809150509250929050565b6000806000606084860312156127bf57600080fd5b83356127ca8161256c565b925060208401356127da8161256c565b91506127e985604086016126cd565b90509250925092565b60006020828403121561280457600080fd5b5035919050565b60008083601f84011261281d57600080fd5b50813567ffffffffffffffff81111561283557600080fd5b6020830191508360208260051b850101111561285057600080fd5b9250929050565b6000806000806000806060878903121561287057600080fd5b863567ffffffffffffffff8082111561288857600080fd5b6128948a838b0161280b565b909850965060208901359150808211156128ad57600080fd5b6128b98a838b0161280b565b909650945060408901359150808211156128d257600080fd5b506128df89828a0161280b565b979a9699509497509295939492505050565b600082601f83011261290257600080fd5b8135602061291261260d836125c8565b82815260059290921b8401810191818101908684111561293157600080fd5b8286015b848110156126555780358352918301918301612935565b60008060006060848603121561296157600080fd5b833567ffffffffffffffff8082111561297957600080fd5b612985878388016125ec565b9450602086013591508082111561299b57600080fd5b6129a7878388016128f1565b935060408601359150808211156129bd57600080fd5b506129ca868287016128f1565b9150509250925092565b600080600080608085870312156129ea57600080fd5b84356129f58161256c565b93506020850135612a058161256c565b9250604085013591506060850135612a1c8161256c565b939692955090935050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a4f57600080fd5b81518015158114611ad657600080fd5b600060208284031215612a7157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600060018201612aa057612aa0612a78565b5060010190565b60208082526027908201527f4f6e6c7920636f6d7074726f6c6c65722063616e2063616c6c207468697320666040820152663ab731ba34b7b760c91b606082015260800190565b600060208284031215612b0057600080fd5b813563ffffffff81168114611ad657600080fd5b60006020808385031215612b2757600080fd5b825167ffffffffffffffff811115612b3e57600080fd5b8301601f81018513612b4f57600080fd5b8051612b5d61260d826125c8565b81815260059190911b82018301908381019087831115612b7c57600080fd5b928401925b828410156124c3578351612b948161256c565b82529284019290840190612b81565b60005b83811015612bbe578181015183820152602001612ba6565b83811115610bfc5750506000910152565b60008151808452612be7816020860160208601612ba3565b601f01601f19169290920160200192915050565b602081526000611ad66020830184612bcf565b600082821015612c2057612c20612a78565b500390565b6000816000190483118215151615612c3f57612c3f612a78565b500290565b60008219821115612c5757612c57612a78565b500190565b6001600160a01b03831681526040602082018190526000906123eb90830184612bcf565b6001600160a01b03848116825283166020820152606060408201819052600090612cac90830184612bcf565b95945050505050565b60208082526037908201527f73657474696e67206c61737420726577617264696e6720626c6f636b20696e2060408201527f7468652070617374206973206e6f7420616c6c6f776564000000000000000000606082015260800190565b60208082526029908201527f7468697320526577617264734469737472696275746f7220697320616c726561604082015268191e481b1bd8dad95960ba1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600082612dc357634e487b7160e01b600052601260045260246000fd5b500490565b60008251612dda818460208701612ba3565b919091019291505056fe7365744c617374526577617264696e67426c6f636b28616464726573735b5d2c75696e7433325b5d2c75696e7433325b5d29736574526577617264546f6b656e53706565647328616464726573735b5d2c75696e743235365b5d2c75696e743235365b5d29a26469706673582212201474ed00ed7ce8b69f43bc3d1d7d04eb0339bf5ee87fbdf788b3116098a88cef64736f6c634300080d0033", + "devdoc": { + "author": "Venus", + "kind": "dev", + "methods": { + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "claimRewardToken(address)": { + "params": { + "holder": "The address to claim REWARD TOKEN for" + } + }, + "claimRewardToken(address,address[])": { + "params": { + "holder": "The address to claim REWARD TOKEN for", + "vTokens": "The list of markets to claim REWARD TOKEN in" + } + }, + "constructor": { + "custom:oz-upgrades-unsafe-allow": "constructor" + }, + "distributeBorrowerRewardToken(address,address,(uint256))": { + "details": "This function should only be called when the user has a borrow position in the market (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook) We avoid an external call to check if they are in the market to save gas because this function is called in many places", + "params": { + "borrower": "The address of the borrower to distribute REWARD TOKEN to", + "marketBorrowIndex": "The current global borrow index of vToken", + "vToken": "The market in which the borrower is interacting" + } + }, + "grantRewardToken(address,uint256)": { + "details": "Note: If there is not enough REWARD TOKEN, we do not perform the transfer all", + "params": { + "amount": "The amount of REWARD TOKEN to (possibly) transfer", + "recipient": "The address of the recipient to transfer REWARD TOKEN to" + } + }, + "initialize(address,address,uint256,address)": { + "details": "Initializes the deployer to owner", + "params": { + "accessControlManager_": "AccessControlManager contract address", + "comptroller_": "Comptroller to attach the reward distributor to", + "loopsLimit_": "Maximum number of iterations for the loops in this contract", + "rewardToken_": "Reward token to distribute" + } + }, + "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" + } + }, + "setContributorRewardTokenSpeed(address,uint256)": { + "params": { + "contributor": "The contributor whose REWARD TOKEN speed to update", + "rewardTokenSpeed": "New REWARD TOKEN speed for contributor" + } + }, + "setLastRewardingBlocks(address[],uint32[],uint32[])": { + "params": { + "borrowLastRewardingBlocks": "New borrow-side REWARD TOKEN last rewarding block for the corresponding market", + "supplyLastRewardingBlocks": "New supply-side REWARD TOKEN last rewarding block for the corresponding market", + "vTokens": "The markets whose REWARD TOKEN last rewarding block to update" + } + }, + "setMaxLoopsLimit(uint256)": { + "params": { + "limit": "Limit for the max loops can execute at a time" + } + }, + "setRewardTokenSpeeds(address[],uint256[],uint256[])": { + "params": { + "borrowSpeeds": "New borrow-side REWARD TOKEN speed for the corresponding market", + "supplySpeeds": "New supply-side REWARD TOKEN speed for the corresponding market", + "vTokens": "The markets whose REWARD TOKEN speed to update" + } + }, + "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." + }, + "updateContributorRewards(address)": { + "params": { + "contributor": "The address to calculate contributor rewards for" + } + } + }, + "title": "`RewardsDistributor`", + "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" + } + ] + }, + "events": { + "BorrowLastRewardingBlockUpdated(address,uint32)": { + "notice": "Emitted when a reward token last rewarding block for borrow is updated" + }, + "ContributorRewardTokenSpeedUpdated(address,uint256)": { + "notice": "Emitted when a new REWARD TOKEN speed is set for a contributor" + }, + "ContributorRewardsUpdated(address,uint256)": { + "notice": "Emitted when a reward for contributor is updated" + }, + "DistributedBorrowerRewardToken(address,address,uint256,uint256,uint256)": { + "notice": "Emitted when REWARD TOKEN is distributed to a borrower" + }, + "DistributedSupplierRewardToken(address,address,uint256,uint256,uint256)": { + "notice": "Emitted when REWARD TOKEN is distributed to a supplier" + }, + "MarketInitialized(address)": { + "notice": "Emitted when a market is initialized" + }, + "MaxLoopsLimitUpdated(uint256,uint256)": { + "notice": "Emitted when max loops limit is set" + }, + "NewAccessControlManager(address,address)": { + "notice": "Emitted when access control manager contract address is changed" + }, + "RewardTokenBorrowIndexUpdated(address,(uint256))": { + "notice": "Emitted when a reward token borrow index is updated" + }, + "RewardTokenBorrowSpeedUpdated(address,uint256)": { + "notice": "Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market" + }, + "RewardTokenGranted(address,uint256)": { + "notice": "Emitted when REWARD TOKEN is granted by admin" + }, + "RewardTokenSupplyIndexUpdated(address)": { + "notice": "Emitted when a reward token supply index is updated" + }, + "RewardTokenSupplySpeedUpdated(address,uint256)": { + "notice": "Emitted when a new supply-side REWARD TOKEN speed is calculated for a market" + }, + "SupplyLastRewardingBlockUpdated(address,uint32)": { + "notice": "Emitted when a reward token last rewarding block for supply is updated" + } + }, + "kind": "user", + "methods": { + "INITIAL_INDEX()": { + "notice": "The initial REWARD TOKEN index for a market" + }, + "accessControlManager()": { + "notice": "Returns the address of the access control manager contract" + }, + "claimRewardToken(address)": { + "notice": "Claim all the rewardToken accrued by holder in all markets" + }, + "claimRewardToken(address,address[])": { + "notice": "Claim all the rewardToken accrued by holder in the specified markets" + }, + "distributeBorrowerRewardToken(address,address,(uint256))": { + "notice": "Calculate reward token accrued by a borrower and possibly transfer it to them Borrowers will begin to accrue after the first interaction with the protocol." + }, + "grantRewardToken(address,uint256)": { + "notice": "Transfer REWARD TOKEN to the recipient" + }, + "initialize(address,address,uint256,address)": { + "notice": "RewardsDistributor initializer" + }, + "lastContributorBlock(address)": { + "notice": "Last block at which a contributor's REWARD TOKEN rewards have been allocated" + }, + "rewardTokenAccrued(address)": { + "notice": "The REWARD TOKEN accrued but not yet transferred to each user" + }, + "rewardTokenBorrowSpeeds(address)": { + "notice": "The rate at which rewardToken is distributed to the corresponding borrow market (per block)" + }, + "rewardTokenBorrowState(address)": { + "notice": "The REWARD TOKEN market borrow state for each market" + }, + "rewardTokenBorrowerIndex(address,address)": { + "notice": "The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN" + }, + "rewardTokenContributorSpeeds(address)": { + "notice": "The portion of REWARD TOKEN that each contributor receives per block" + }, + "rewardTokenSupplierIndex(address,address)": { + "notice": "The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN" + }, + "rewardTokenSupplySpeeds(address)": { + "notice": "The rate at which rewardToken is distributed to the corresponding supply market (per block)" + }, + "rewardTokenSupplyState(address)": { + "notice": "The REWARD TOKEN market supply state for each market" + }, + "setAccessControlManager(address)": { + "notice": "Sets the address of AccessControlManager" + }, + "setContributorRewardTokenSpeed(address,uint256)": { + "notice": "Set REWARD TOKEN speed for a single contributor" + }, + "setLastRewardingBlocks(address[],uint32[],uint32[])": { + "notice": "Set REWARD TOKEN last rewarding block for the specified markets" + }, + "setMaxLoopsLimit(uint256)": { + "notice": "Set the limit for the loops can iterate to avoid the DOS" + }, + "setRewardTokenSpeeds(address[],uint256[],uint256[])": { + "notice": "Set REWARD TOKEN borrow and supply speeds for the specified markets" + }, + "updateContributorRewards(address)": { + "notice": "Calculate additional accrued REWARD TOKEN for a contributor since last accrual" + } + }, + "notice": "Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol. Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool. Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward token to be released each block for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting their contributor reward token speed, which similarly allocates a fixed amount of reward token per block. The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 290, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 293, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1397, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 162, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 282, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 71, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "_pendingOwner", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 150, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 5019, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "_accessControlManager", + "offset": 0, + "slot": "151", + "type": "t_contract(IAccessControlManagerV8)5204" + }, + { + "astId": 5024, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 14017, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "maxLoopsLimit", + "offset": 0, + "slot": "201", + "type": "t_uint256" + }, + { + "astId": 14022, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 14973, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "rewardTokenSupplyState", + "offset": 0, + "slot": "251", + "type": "t_mapping(t_address,t_struct(RewardToken)14963_storage)" + }, + { + "astId": 14980, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "rewardTokenSupplierIndex", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 14985, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "rewardTokenAccrued", + "offset": 0, + "slot": "253", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 14990, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "rewardTokenBorrowSpeeds", + "offset": 0, + "slot": "254", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 14995, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "rewardTokenSupplySpeeds", + "offset": 0, + "slot": "255", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 15001, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "rewardTokenBorrowState", + "offset": 0, + "slot": "256", + "type": "t_mapping(t_address,t_struct(RewardToken)14963_storage)" + }, + { + "astId": 15006, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "rewardTokenContributorSpeeds", + "offset": 0, + "slot": "257", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 15011, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "lastContributorBlock", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 15018, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "rewardTokenBorrowerIndex", + "offset": 0, + "slot": "259", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 15021, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "comptroller", + "offset": 0, + "slot": "260", + "type": "t_contract(Comptroller)11230" + }, + { + "astId": 15024, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "rewardToken", + "offset": 0, + "slot": "261", + "type": "t_contract(IERC20Upgradeable)614" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "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(Comptroller)11230": { + "encoding": "inplace", + "label": "contract Comptroller", + "numberOfBytes": "20" + }, + "t_contract(IAccessControlManagerV8)5204": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_contract(IERC20Upgradeable)614": { + "encoding": "inplace", + "label": "contract IERC20Upgradeable", + "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_struct(RewardToken)14963_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct RewardsDistributor.RewardToken)", + "numberOfBytes": "32", + "value": "t_struct(RewardToken)14963_storage" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(RewardToken)14963_storage": { + "encoding": "inplace", + "label": "struct RewardsDistributor.RewardToken", + "members": [ + { + "astId": 14958, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "index", + "offset": 0, + "slot": "0", + "type": "t_uint224" + }, + { + "astId": 14960, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "block", + "offset": 28, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 14962, + "contract": "contracts/Rewards/RewardsDistributor.sol:RewardsDistributor", + "label": "lastRewardingBlock", + "offset": 0, + "slot": "1", + "type": "t_uint32" + } + ], + "numberOfBytes": "64" + }, + "t_uint224": { + "encoding": "inplace", + "label": "uint224", + "numberOfBytes": "28" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} diff --git a/deployments/sepolia/VTokenBeacon.json b/deployments/sepolia/VTokenBeacon.json new file mode 100644 index 000000000..9500fb017 --- /dev/null +++ b/deployments/sepolia/VTokenBeacon.json @@ -0,0 +1,206 @@ +{ + "address": "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "implementation", + "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": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x7f29f92167b9ec817e224eec9916d0c6bce5ce0e57a665c84f6990744c1f703b", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "transactionIndex": 37, + "gasUsed": "292193", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000080000000001000000000000000000000000020000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000020000000020000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xcc526cbf8673ad43b95f93713fdda2bf81456633a9e92db4878e4afc88d0facc", + "transactionHash": "0x7f29f92167b9ec817e224eec9916d0c6bce5ce0e57a665c84f6990744c1f703b", + "logs": [ + { + "transactionIndex": 37, + "blockNumber": 4776624, + "transactionHash": "0x7f29f92167b9ec817e224eec9916d0c6bce5ce0e57a665c84f6990744c1f703b", + "address": "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 46, + "blockHash": "0xcc526cbf8673ad43b95f93713fdda2bf81456633a9e92db4878e4afc88d0facc" + } + ], + "blockNumber": 4776624, + "cumulativeGasUsed": "9264771", + "status": 1, + "byzantium": true + }, + "args": ["0x3630AD592d07294aB37336b734aB053685dDD35c"], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"implementation\",\"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\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their implementation contract, which is where they will delegate all function calls. An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\",\"events\":{\"Upgraded(address)\":{\"details\":\"Emitted when the implementation returned by the beacon is changed.\"}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the beacon.\"},\"implementation()\":{\"details\":\"Returns the current implementation address.\"},\"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. 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.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgradeTo(address)\":{\"details\":\"Upgrades the beacon to a new implementation. Emits an {Upgraded} event. Requirements: - msg.sender must be the owner of the contract. - `newImplementation` must be a contract.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol\":\"UpgradeableBeacon\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x6ec71aef5659f3f74011169948d2fcda8c6599be5bb38f986380a8737f96cc0f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506040516104e43803806104e483398101604081905261002f91610151565b61003833610047565b61004181610097565b50610181565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6100aa8161014260201b6101a01760201c565b6101205760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f60448201527f6e206973206e6f74206120636f6e747261637400000000000000000000000000606482015260840160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03163b151590565b60006020828403121561016357600080fd5b81516001600160a01b038116811461017a57600080fd5b9392505050565b610354806101906000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80633659cfe61461005c5780635c60da1b14610071578063715018a61461009a5780638da5cb5b146100a2578063f2fde38b146100b3575b600080fd5b61006f61006a3660046102ee565b6100c6565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006f61010e565b6000546001600160a01b031661007e565b61006f6100c13660046102ee565b610122565b6100ce6101af565b6100d781610209565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6101166101af565b610120600061029e565b565b61012a6101af565b6001600160a01b0381166101945760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019d8161029e565b50565b6001600160a01b03163b151590565b6000546001600160a01b031633146101205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161018b565b6001600160a01b0381163b61027c5760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b606482015260840161018b565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561030057600080fd5b81356001600160a01b038116811461031757600080fd5b939250505056fea2646970667358221220dbaafc37b41702e4f412c3196a46d19f8c0bba820e2f5b5f81b00307ad83d17064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80633659cfe61461005c5780635c60da1b14610071578063715018a61461009a5780638da5cb5b146100a2578063f2fde38b146100b3575b600080fd5b61006f61006a3660046102ee565b6100c6565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006f61010e565b6000546001600160a01b031661007e565b61006f6100c13660046102ee565b610122565b6100ce6101af565b6100d781610209565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6101166101af565b610120600061029e565b565b61012a6101af565b6001600160a01b0381166101945760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019d8161029e565b50565b6001600160a01b03163b151590565b6000546001600160a01b031633146101205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161018b565b6001600160a01b0381163b61027c5760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b606482015260840161018b565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561030057600080fd5b81356001600160a01b038116811461031757600080fd5b939250505056fea2646970667358221220dbaafc37b41702e4f412c3196a46d19f8c0bba820e2f5b5f81b00307ad83d17064736f6c634300080d0033", + "devdoc": { + "details": "This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their implementation contract, which is where they will delegate all function calls. An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.", + "events": { + "Upgraded(address)": { + "details": "Emitted when the implementation returned by the beacon is changed." + } + }, + "kind": "dev", + "methods": { + "constructor": { + "details": "Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the beacon." + }, + "implementation()": { + "details": "Returns the current implementation address." + }, + "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. 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." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgradeTo(address)": { + "details": "Upgrades the beacon to a new implementation. Emits an {Upgraded} event. Requirements: - msg.sender must be the owner of the contract. - `newImplementation` must be a contract." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1795, + "contract": "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol:UpgradeableBeacon", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 2375, + "contract": "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol:UpgradeableBeacon", + "label": "_implementation", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} diff --git a/deployments/sepolia/VTokenImpl.json b/deployments/sepolia/VTokenImpl.json new file mode 100644 index 000000000..6f1aaad4f --- /dev/null +++ b/deployments/sepolia/VTokenImpl.json @@ -0,0 +1,3021 @@ +{ + "address": "0x3630AD592d07294aB37336b734aB053685dDD35c", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "actualAddAmount", + "type": "uint256" + } + ], + "name": "AddReservesFactorFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowCashNotAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "ForceLiquidateBorrowUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "HealBorrowUnauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "LiquidateAccrueCollateralInterestFailed", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsUintMax", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsZero", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCollateralFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateSeizeLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "MintFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "ProtocolSeizeShareTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemTransferOutNotPossible", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashNotAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashValidation", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RepayBorrowFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetInterestRateModelFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorBoundsCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "TransferNotAllowed", + "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": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" + } + ], + "name": "BadDebtIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" + } + ], + "name": "BadDebtRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "HealBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" + } + ], + "name": "Mint", + "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": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldProtocolSeizeShareMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa", + "type": "uint256" + } + ], + "name": "NewProtocolSeizeShare", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldShortfall", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newShortfall", + "type": "address" + } + ], + "name": "NewShortfallContract", + "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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ProtocolSeize", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "SpreadReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "NO_ERROR", + "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": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "addReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "badDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "recoveredAmount_", + "type": "uint256" + } + ], + "name": "badDebtRecovered", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "bool", + "name": "skipLiquidityCheck", + "type": "bool" + } + ], + "name": "forceLiquidateBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vTokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "healBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "shortfall", + "type": "address" + }, + { + "internalType": "address payable", + "name": "protocolShareReserve", + "type": "address" + } + ], + "internalType": "struct VTokenInterface.RiskManagementInit", + "name": "riskManagement", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "protocolSeizeShareMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "reduceReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "setInterestRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa_", + "type": "uint256" + } + ], + "name": "setProtocolSeizeShare", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "protocolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newReduceReservesBlockDelta", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "setReserveFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "shortfall_", + "type": "address" + } + ], + "name": "setShortfallContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x6430af2afd8bdca74fbd53028dedf60158916d554cef48582fbd9861d003e545", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x3630AD592d07294aB37336b734aB053685dDD35c", + "transactionIndex": 22, + "gasUsed": "4088389", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000008000000000000000000000000000000000000000000000004000000000000000", + "blockHash": "0xb666072b3dacb60ba0ead9b8233989dc16cb29ac87adc70ff5c6a8e8bf387985", + "transactionHash": "0x6430af2afd8bdca74fbd53028dedf60158916d554cef48582fbd9861d003e545", + "logs": [ + { + "transactionIndex": 22, + "blockNumber": 4776623, + "transactionHash": "0x6430af2afd8bdca74fbd53028dedf60158916d554cef48582fbd9861d003e545", + "address": "0x3630AD592d07294aB37336b734aB053685dDD35c", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", + "logIndex": 31, + "blockHash": "0xb666072b3dacb60ba0ead9b8233989dc16cb29ac87adc70ff5c6a8e8bf387985" + } + ], + "blockNumber": 4776623, + "cumulativeGasUsed": "6903354", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actualAddAmount\",\"type\":\"uint256\"}],\"name\":\"AddReservesFactorFreshCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowCashNotAvailable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowFreshnessCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ForceLiquidateBorrowUnauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HealBorrowUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"}],\"name\":\"LiquidateAccrueCollateralInterestFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidateCloseAmountIsUintMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidateCloseAmountIsZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidateCollateralFreshnessCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidateFreshnessCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidateLiquidatorIsBorrower\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidateSeizeLiquidatorIsBorrower\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MintFreshnessCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProtocolSeizeShareTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RedeemFreshnessCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RedeemTransferOutNotPossible\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReduceReservesCashNotAvailable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReduceReservesCashValidation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReduceReservesFreshCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepayBorrowFreshnessCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SetInterestRateModelFreshCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SetReserveFactorBoundsCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SetReserveFactorFreshCheck\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferNotAllowed\",\"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\":false,\"internalType\":\"uint256\",\"name\":\"cashPrior\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"interestAccumulated\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"borrowIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"}],\"name\":\"AccrueInterest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"badDebtDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"badDebtOld\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"badDebtNew\",\"type\":\"uint256\"}],\"name\":\"BadDebtIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"badDebtOld\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"badDebtNew\",\"type\":\"uint256\"}],\"name\":\"BadDebtRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"accountBorrows\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"}],\"name\":\"Borrow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"HealBorrow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"LiquidateBorrow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"accountBalance\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"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\":\"contract ComptrollerInterface\",\"name\":\"oldComptroller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"newComptroller\",\"type\":\"address\"}],\"name\":\"NewComptroller\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract InterestRateModel\",\"name\":\"oldInterestRateModel\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract InterestRateModel\",\"name\":\"newInterestRateModel\",\"type\":\"address\"}],\"name\":\"NewMarketInterestRateModel\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldProtocolSeizeShareMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newProtocolSeizeShareMantissa\",\"type\":\"uint256\"}],\"name\":\"NewProtocolSeizeShare\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldProtocolShareReserve\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newProtocolShareReserve\",\"type\":\"address\"}],\"name\":\"NewProtocolShareReserve\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldReduceReservesBlockDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newReduceReservesBlockDelta\",\"type\":\"uint256\"}],\"name\":\"NewReduceReservesBlockDelta\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldReserveFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newReserveFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewReserveFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldShortfall\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newShortfall\",\"type\":\"address\"}],\"name\":\"NewShortfallContract\",\"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\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ProtocolSeize\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"accountBalance\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"accountBorrows\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"}],\"name\":\"RepayBorrow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"benefactor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"addAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTotalReserves\",\"type\":\"uint256\"}],\"name\":\"ReservesAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"protocolShareReserve\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reduceAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTotalReserves\",\"type\":\"uint256\"}],\"name\":\"SpreadReservesReduced\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NO_ERROR\",\"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\":[],\"name\":\"accrualBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accrueInterest\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"addAmount\",\"type\":\"uint256\"}],\"name\":\"addReserves\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"badDebt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"recoveredAmount_\",\"type\":\"uint256\"}],\"name\":\"badDebtRecovered\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOfUnderlying\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"borrowBalanceCurrent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"borrowBalanceStored\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptroller\",\"outputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exchangeRateCurrent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exchangeRateStored\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"contract VTokenInterface\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"skipLiquidityCheck\",\"type\":\"bool\"}],\"name\":\"forceLiquidateBorrow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"vTokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRate\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCash\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"healBorrow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"underlying_\",\"type\":\"address\"},{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"comptroller_\",\"type\":\"address\"},{\"internalType\":\"contract InterestRateModel\",\"name\":\"interestRateModel_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"initialExchangeRateMantissa_\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"shortfall\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"protocolShareReserve\",\"type\":\"address\"}],\"internalType\":\"struct VTokenInterface.RiskManagementInit\",\"name\":\"riskManagement\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"interestRateModel\",\"outputs\":[{\"internalType\":\"contract InterestRateModel\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isVToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"contract VTokenInterface\",\"name\":\"vTokenCollateral\",\"type\":\"address\"}],\"name\":\"liquidateBorrow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"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\":\"protocolSeizeShareMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolShareReserve\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"}],\"name\":\"redeemUnderlying\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reduceAmount\",\"type\":\"uint256\"}],\"name\":\"reduceReserves\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"reduceReservesBlockDelta\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"reduceReservesBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"reserveFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract InterestRateModel\",\"name\":\"newInterestRateModel\",\"type\":\"address\"}],\"name\":\"setInterestRateModel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newProtocolSeizeShareMantissa_\",\"type\":\"uint256\"}],\"name\":\"setProtocolSeizeShare\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"protocolShareReserve_\",\"type\":\"address\"}],\"name\":\"setProtocolShareReserve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newReduceReservesBlockDelta\",\"type\":\"uint256\"}],\"name\":\"setReduceReservesBlockDelta\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newReserveFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"setReserveFactor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfall_\",\"type\":\"address\"}],\"name\":\"setShortfallContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"supplyRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalBorrows\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalBorrowsCurrent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"underlying\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"accrueInterest()\":{\"custom:access\":\"Not restricted\",\"custom:event\":\"Emits AccrueInterest event on success\",\"details\":\"This calculates interest accrued from the last checkpointed block up to the current block and writes new checkpoint to storage and reduce spread reserves to protocol share reserve if currentBlock - reduceReservesBlockNumber >= blockDelta\",\"returns\":{\"_0\":\"Always NO_ERROR\"}},\"addReserves(uint256)\":{\"custom:access\":\"Not restricted\",\"custom:event\":\"Emits ReservesAdded event; may emit AccrueInterest\",\"params\":{\"addAmount\":\"The amount of underlying token to add as reserves\"}},\"allowance(address,address)\":{\"params\":{\"owner\":\"The address of the account which owns the tokens to be spent\",\"spender\":\"The address of the account which may transfer tokens\"},\"returns\":{\"_0\":\"amount The number of tokens allowed to be spent (type(uint256).max means infinite)\"}},\"approve(address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when spender address is zero\",\"custom:event\":\"Emits Approval event\",\"details\":\"This will overwrite the approval amount for `spender` and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\",\"params\":{\"amount\":\"The number of tokens that are approved (uint256.max means infinite)\",\"spender\":\"The address of the account which may transfer tokens\"},\"returns\":{\"_0\":\"success Whether or not the approval succeeded\"}},\"badDebtRecovered(uint256)\":{\"custom:access\":\"Only Shortfall contract\",\"custom:event\":\"Emits BadDebtRecovered event\",\"details\":\"Called only when bad debt is recovered from auction\",\"params\":{\"recoveredAmount_\":\"The amount of bad debt recovered\"}},\"balanceOf(address)\":{\"params\":{\"owner\":\"The address of the account to query\"},\"returns\":{\"_0\":\"amount The number of tokens owned by `owner`\"}},\"balanceOfUnderlying(address)\":{\"details\":\"This also accrues interest in a transaction\",\"params\":{\"owner\":\"The address of the account to query\"},\"returns\":{\"_0\":\"amount The amount of underlying owned by `owner`\"}},\"borrow(uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"BorrowCashNotAvailable is thrown when the protocol has insufficient cash\",\"custom:event\":\"Emits Borrow event; may emit AccrueInterest\",\"params\":{\"borrowAmount\":\"The amount of the underlying asset to borrow\"},\"returns\":{\"_0\":\"error Always NO_ERROR for compatibility with Venus core tooling\"}},\"borrowBalanceCurrent(address)\":{\"params\":{\"account\":\"The address whose balance should be calculated after updating borrowIndex\"},\"returns\":{\"_0\":\"borrowBalance The calculated balance\"}},\"borrowBalanceStored(address)\":{\"params\":{\"account\":\"The address whose balance should be calculated\"},\"returns\":{\"_0\":\"borrowBalance The calculated balance\"}},\"borrowRatePerBlock()\":{\"returns\":{\"_0\":\"rate The borrow interest rate per block, scaled by 1e18\"}},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"decreaseAllowance(address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when spender address is zero\",\"custom:event\":\"Emits Approval event\",\"params\":{\"spender\":\"The address of the account which may transfer tokens\",\"subtractedValue\":\"The number of tokens to remove from total approval\"},\"returns\":{\"_0\":\"success Whether or not the approval succeeded\"}},\"exchangeRateCurrent()\":{\"returns\":{\"_0\":\"exchangeRate Calculated exchange rate scaled by 1e18\"}},\"exchangeRateStored()\":{\"details\":\"This function does not accrue interest before calculating the exchange rate\",\"returns\":{\"_0\":\"exchangeRate Calculated exchange rate scaled by 1e18\"}},\"forceLiquidateBorrow(address,address,uint256,address,bool)\":{\"custom:access\":\"Only Comptroller\",\"custom:error\":\"ForceLiquidateBorrowUnauthorized is thrown when the request does not come from ComptrollerLiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vTokenLiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vTokenLiquidateLiquidatorIsBorrower is thrown when trying to liquidate selfLiquidateCloseAmountIsZero is thrown when repayment amount is zeroLiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\",\"custom:event\":\"Emits LiquidateBorrow event; may emit AccrueInterest\",\"params\":{\"borrower\":\"The borrower of this vToken to be liquidated\",\"liquidator\":\"The address repaying the borrow and seizing collateral\",\"repayAmount\":\"The amount of the underlying borrowed asset to repay\",\"skipLiquidityCheck\":\"If set to true, allows to liquidate up to 100% of the borrow regardless of the account liquidity\",\"vTokenCollateral\":\"The market in which to seize collateral from the borrower\"}},\"getAccountSnapshot(address)\":{\"details\":\"This is used by comptroller to more efficiently perform liquidity checks.\",\"params\":{\"account\":\"Address of the account to snapshot\"},\"returns\":{\"borrowBalance\":\"Amount owed in terms of underlying\",\"error\":\"Always NO_ERROR for compatibility with Venus core tooling\",\"exchangeRate\":\"Stored exchange rate\",\"vTokenBalance\":\"User's balance of vTokens\"}},\"getCash()\":{\"returns\":{\"_0\":\"cash The quantity of underlying asset owned by this contract\"}},\"healBorrow(address,address,uint256)\":{\"custom:access\":\"Only Comptroller\",\"custom:error\":\"HealBorrowUnauthorized is thrown when the request does not come from Comptroller\",\"custom:event\":\"Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\",\"details\":\"This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume the Comptroller does all the necessary checks before calling this function.\",\"params\":{\"borrower\":\"account to heal\",\"payer\":\"account who repays the debt\",\"repayAmount\":\"amount to repay\"}},\"increaseAllowance(address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when spender address is zero\",\"custom:event\":\"Emits Approval event\",\"params\":{\"addedValue\":\"The number of additional tokens spender can transfer\",\"spender\":\"The address of the account which may transfer tokens\"},\"returns\":{\"_0\":\"success Whether or not the approval succeeded\"}},\"initialize(address,address,address,uint256,string,string,uint8,address,address,(address,address),uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when admin address is zeroZeroAddressNotAllowed is thrown when shortfall contract address is zeroZeroAddressNotAllowed is thrown when protocol share reserve address is zero\",\"params\":{\"accessControlManager_\":\"AccessControlManager contract address\",\"admin_\":\"Address of the administrator of this token\",\"comptroller_\":\"The address of the Comptroller\",\"decimals_\":\"ERC-20 decimal precision of this token\",\"initialExchangeRateMantissa_\":\"The initial exchange rate, scaled by 1e18\",\"interestRateModel_\":\"The address of the interest rate model\",\"name_\":\"ERC-20 name of this token\",\"reserveFactorMantissa_\":\"Percentage of borrow interest that goes to reserves (from 0 to 1e18)\",\"riskManagement\":\"Addresses of risk & income related contracts\",\"symbol_\":\"ERC-20 symbol of this token\",\"underlying_\":\"The address of the underlying asset\"}},\"isVToken()\":{\"returns\":{\"_0\":\"Always true\"}},\"liquidateBorrow(address,uint256,address)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vTokenLiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vTokenLiquidateLiquidatorIsBorrower is thrown when trying to liquidate selfLiquidateCloseAmountIsZero is thrown when repayment amount is zeroLiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\",\"custom:event\":\"Emits LiquidateBorrow event; may emit AccrueInterest\",\"params\":{\"borrower\":\"The borrower of this vToken to be liquidated\",\"repayAmount\":\"The amount of the underlying borrowed asset to repay\",\"vTokenCollateral\":\"The market in which to seize collateral from the borrower\"},\"returns\":{\"_0\":\"error Always NO_ERROR for compatibility with Venus core tooling\"}},\"mint(uint256)\":{\"custom:access\":\"Not restricted\",\"custom:event\":\"Emits Mint and Transfer events; may emit AccrueInterest\",\"details\":\"Accrues interest whether or not the operation succeeds, unless reverted\",\"params\":{\"mintAmount\":\"The amount of the underlying asset to supply\"},\"returns\":{\"_0\":\"error Always NO_ERROR for compatibility with Venus core tooling\"}},\"mintBehalf(address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when minter address is zero\",\"custom:event\":\"Emits Mint and Transfer events; may emit AccrueInterest\",\"details\":\"Accrues interest whether or not the operation succeeds, unless reverted\",\"params\":{\"mintAmount\":\"The amount of the underlying asset to supply\",\"minter\":\"User whom the supply will be attributed to\"},\"returns\":{\"_0\":\"error Always NO_ERROR for compatibility with Venus core tooling\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"redeem(uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\",\"custom:event\":\"Emits Redeem and Transfer events; may emit AccrueInterest\",\"details\":\"Accrues interest whether or not the operation succeeds, unless reverted\",\"params\":{\"redeemTokens\":\"The number of vTokens to redeem into underlying\"},\"returns\":{\"_0\":\"error Always NO_ERROR for compatibility with Venus core tooling\"}},\"redeemUnderlying(uint256)\":{\"details\":\"Accrues interest whether or not the operation succeeds, unless reverted\",\"params\":{\"redeemAmount\":\"The amount of underlying to receive from redeeming vTokens\"},\"returns\":{\"_0\":\"error Always NO_ERROR for compatibility with Venus core tooling\"}},\"reduceReserves(uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cashReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\",\"custom:event\":\"Emits ReservesReduced event; may emit AccrueInterest\",\"details\":\"Gracefully return if reserves already reduced in accrueInterest\",\"params\":{\"reduceAmount\":\"Amount of reduction to reserves\"}},\"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.\"},\"repayBorrow(uint256)\":{\"custom:access\":\"Not restricted\",\"custom:event\":\"Emits RepayBorrow event; may emit AccrueInterest\",\"params\":{\"repayAmount\":\"The amount to repay, or type(uint256).max for the full outstanding amount\"},\"returns\":{\"_0\":\"error Always NO_ERROR for compatibility with Venus core tooling\"}},\"repayBorrowBehalf(address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:event\":\"Emits RepayBorrow event; may emit AccrueInterest\",\"params\":{\"borrower\":\"the account with the debt being payed off\",\"repayAmount\":\"The amount to repay, or type(uint256).max for the full outstanding amount\"},\"returns\":{\"_0\":\"error Always NO_ERROR for compatibility with Venus core tooling\"}},\"seize(address,address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\",\"custom:event\":\"Emits Transfer, ReservesAdded events\",\"details\":\"Will fail unless called by another vToken during the process of liquidation. It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\",\"params\":{\"borrower\":\"The account having collateral seized\",\"liquidator\":\"The account receiving seized collateral\",\"seizeTokens\":\"The number of vTokens to seize\"}},\"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\"}},\"setInterestRateModel(address)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManager\",\"custom:event\":\"Emits NewMarketInterestRateModel event; may emit AccrueInterest\",\"details\":\"Admin function to accrue interest and update the interest rate model\",\"params\":{\"newInterestRateModel\":\"the new interest rate model to use\"}},\"setProtocolSeizeShare(uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerProtocolSeizeShareTooBig is thrown when the new seize share is too high\",\"custom:event\":\"Emits NewProtocolSeizeShare event on success\",\"details\":\"must be equal or less than liquidation incentive - 1\",\"params\":{\"newProtocolSeizeShareMantissa_\":\"new protocol share mantissa\"}},\"setProtocolShareReserve(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\",\"params\":{\"protocolShareReserve_\":\"The address of the protocol share reserve contract\"}},\"setReduceReservesBlockDelta(uint256)\":{\"custom:access\":\"Only Governance\",\"params\":{\"_newReduceReservesBlockDelta\":\"block difference value\"}},\"setReserveFactor(uint256)\":{\"custom:access\":\"Controlled by AccessControlManager\",\"custom:error\":\"Unauthorized error is thrown when the call is not authorized by AccessControlManagerSetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\",\"custom:event\":\"Emits NewReserveFactor event; may emit AccrueInterest\",\"details\":\"Admin function to accrue interest and set a new reserve factor\",\"params\":{\"newReserveFactorMantissa\":\"New reserve factor (from 0 to 1e18)\"}},\"setShortfallContract(address)\":{\"custom:access\":\"Only Governance\",\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfall_\":\"The address of the shortfall contract\"}},\"supplyRatePerBlock()\":{\"returns\":{\"_0\":\"rate The supply interest rate per block, scaled by 1e18\"}},\"sweepToken(address)\":{\"custom:access\":\"Only Governance\",\"params\":{\"token\":\"The address of the ERC-20 token to sweep\"}},\"totalBorrowsCurrent()\":{\"returns\":{\"_0\":\"totalBorrows The total borrows with interest\"}},\"transfer(address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"TransferNotAllowed is thrown if trying to transfer to self\",\"custom:event\":\"Emits Transfer event on success\",\"params\":{\"amount\":\"The number of tokens to transfer\",\"dst\":\"The address of the destination account\"},\"returns\":{\"_0\":\"success True if the transfer succeeded, reverts otherwise\"}},\"transferFrom(address,address,uint256)\":{\"custom:access\":\"Not restricted\",\"custom:error\":\"TransferNotAllowed is thrown if trying to transfer to self\",\"custom:event\":\"Emits Transfer event on success\",\"params\":{\"amount\":\"The number of tokens to transfer\",\"dst\":\"The address of the destination account\",\"src\":\"The address of the source account\"},\"returns\":{\"_0\":\"success True if the transfer succeeded, reverts otherwise\"}},\"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.\"}},\"title\":\"VToken\",\"version\":1},\"userdoc\":{\"errors\":{\"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\":{\"AccrueInterest(uint256,uint256,uint256,uint256)\":{\"notice\":\"Event emitted when interest is accrued\"},\"Approval(address,address,uint256)\":{\"notice\":\"EIP20 Approval event\"},\"BadDebtIncreased(address,uint256,uint256,uint256)\":{\"notice\":\"Event emitted when bad debt is accumulated on a market\"},\"BadDebtRecovered(uint256,uint256)\":{\"notice\":\"Event emitted when bad debt is recovered via an auction\"},\"Borrow(address,uint256,uint256,uint256)\":{\"notice\":\"Event emitted when underlying is borrowed\"},\"HealBorrow(address,address,uint256)\":{\"notice\":\"Event emitted when healing the borrow\"},\"LiquidateBorrow(address,address,uint256,address,uint256)\":{\"notice\":\"Event emitted when a borrow is liquidated\"},\"Mint(address,uint256,uint256,uint256)\":{\"notice\":\"Event emitted when tokens are minted\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"NewComptroller(address,address)\":{\"notice\":\"Event emitted when comptroller is changed\"},\"NewMarketInterestRateModel(address,address)\":{\"notice\":\"Event emitted when interestRateModel is changed\"},\"NewProtocolSeizeShare(uint256,uint256)\":{\"notice\":\"Event emitted when protocol seize share is changed\"},\"NewProtocolShareReserve(address,address)\":{\"notice\":\"Event emitted when protocol share reserve contract address is changed\"},\"NewReduceReservesBlockDelta(uint256,uint256)\":{\"notice\":\"Event emitted when reduce reserves block delta is changed\"},\"NewReserveFactor(uint256,uint256)\":{\"notice\":\"Event emitted when the reserve factor is changed\"},\"NewShortfallContract(address,address)\":{\"notice\":\"Event emitted when shortfall contract address is changed\"},\"ProtocolSeize(address,address,uint256)\":{\"notice\":\"Event emitted when liquidation reserves are reduced\"},\"Redeem(address,uint256,uint256,uint256)\":{\"notice\":\"Event emitted when tokens are redeemed\"},\"RepayBorrow(address,address,uint256,uint256,uint256)\":{\"notice\":\"Event emitted when a borrow is repaid\"},\"ReservesAdded(address,uint256,uint256)\":{\"notice\":\"Event emitted when the reserves are added\"},\"SpreadReservesReduced(address,uint256,uint256)\":{\"notice\":\"Event emitted when the spread reserves are reduced\"},\"SweepToken(address)\":{\"notice\":\"Event emitted when tokens are swept\"},\"Transfer(address,address,uint256)\":{\"notice\":\"EIP20 Transfer event\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"accrualBlockNumber()\":{\"notice\":\"Block number that interest was last accrued at\"},\"accrueInterest()\":{\"notice\":\"Applies accrued interest to total borrows and reserves\"},\"addReserves(uint256)\":{\"notice\":\"The sender adds to reserves.\"},\"allowance(address,address)\":{\"notice\":\"Get the current allowance from `owner` for `spender`\"},\"approve(address,uint256)\":{\"notice\":\"Approve `spender` to transfer up to `amount` from `src`\"},\"badDebt()\":{\"notice\":\"Total bad debt of the market\"},\"badDebtRecovered(uint256)\":{\"notice\":\"Updates bad debt\"},\"balanceOf(address)\":{\"notice\":\"Get the token balance of the `owner`\"},\"balanceOfUnderlying(address)\":{\"notice\":\"Get the underlying balance of the `owner`\"},\"borrow(uint256)\":{\"notice\":\"Sender borrows assets from the protocol to their own address\"},\"borrowBalanceCurrent(address)\":{\"notice\":\"Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\"},\"borrowBalanceStored(address)\":{\"notice\":\"Return the borrow balance of account based on stored data\"},\"borrowIndex()\":{\"notice\":\"Accumulator of the total earned interest rate since the opening of the market\"},\"borrowRatePerBlock()\":{\"notice\":\"Returns the current per-block borrow interest rate for this vToken\"},\"comptroller()\":{\"notice\":\"Contract which oversees inter-vToken operations\"},\"decimals()\":{\"notice\":\"EIP-20 token decimals for this token\"},\"decreaseAllowance(address,uint256)\":{\"notice\":\"Decreases approval for `spender`\"},\"exchangeRateCurrent()\":{\"notice\":\"Accrue interest then return the up-to-date exchange rate\"},\"exchangeRateStored()\":{\"notice\":\"Calculates the exchange rate from the underlying to the VToken\"},\"forceLiquidateBorrow(address,address,uint256,address,bool)\":{\"notice\":\"The extended version of liquidations, callable only by Comptroller. May skip the close factor check. The collateral seized is transferred to the liquidator.\"},\"getAccountSnapshot(address)\":{\"notice\":\"Get a snapshot of the account's balances, and the cached exchange rate\"},\"getCash()\":{\"notice\":\"Get cash balance of this vToken in the underlying asset\"},\"healBorrow(address,address,uint256)\":{\"notice\":\"Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully. We assume that Comptroller does the seizing, so this function is only available to Comptroller.\"},\"increaseAllowance(address,uint256)\":{\"notice\":\"Increase approval for `spender`\"},\"initialize(address,address,address,uint256,string,string,uint8,address,address,(address,address),uint256)\":{\"notice\":\"Construct a new money market\"},\"interestRateModel()\":{\"notice\":\"Model which tells what the current interest rate should be\"},\"isVToken()\":{\"notice\":\"Indicator that this is a VToken contract (for inspection)\"},\"liquidateBorrow(address,uint256,address)\":{\"notice\":\"The sender liquidates the borrowers collateral. The collateral seized is transferred to the liquidator.\"},\"mint(uint256)\":{\"notice\":\"Sender supplies assets into the market and receives vTokens in exchange\"},\"mintBehalf(address,uint256)\":{\"notice\":\"Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\"},\"name()\":{\"notice\":\"EIP-20 token name for this token\"},\"protocolSeizeShareMantissa()\":{\"notice\":\"Share of seized collateral that is added to reserves\"},\"protocolShareReserve()\":{\"notice\":\"Protocol share Reserve contract address\"},\"redeem(uint256)\":{\"notice\":\"Sender redeems vTokens in exchange for the underlying asset\"},\"redeemUnderlying(uint256)\":{\"notice\":\"Sender redeems vTokens in exchange for a specified amount of underlying asset\"},\"reduceReserves(uint256)\":{\"notice\":\"Accrues interest and reduces reserves by transferring to the protocol reserve contract\"},\"reduceReservesBlockDelta()\":{\"notice\":\"delta block after which reserves will be reduced\"},\"reduceReservesBlockNumber()\":{\"notice\":\"last block number at which reserves were reduced\"},\"repayBorrow(uint256)\":{\"notice\":\"Sender repays their own borrow\"},\"repayBorrowBehalf(address,uint256)\":{\"notice\":\"Sender repays a borrow belonging to borrower\"},\"reserveFactorMantissa()\":{\"notice\":\"Fraction of interest currently set aside for reserves\"},\"seize(address,address,uint256)\":{\"notice\":\"Transfers collateral tokens (this market) to the liquidator.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setInterestRateModel(address)\":{\"notice\":\"accrues interest and updates the interest rate model using _setInterestRateModelFresh\"},\"setProtocolSeizeShare(uint256)\":{\"notice\":\"sets protocol share accumulated from liquidations\"},\"setProtocolShareReserve(address)\":{\"notice\":\"Sets protocol share reserve contract address\"},\"setReduceReservesBlockDelta(uint256)\":{\"notice\":\"A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve\"},\"setReserveFactor(uint256)\":{\"notice\":\"accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\"},\"setShortfallContract(address)\":{\"notice\":\"Sets shortfall contract address\"},\"shortfall()\":{\"notice\":\"Storage of Shortfall contract address\"},\"supplyRatePerBlock()\":{\"notice\":\"Returns the current per-block supply interest rate for this v\"},\"sweepToken(address)\":{\"notice\":\"A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\"},\"symbol()\":{\"notice\":\"EIP-20 token symbol for this token\"},\"totalBorrows()\":{\"notice\":\"Total amount of outstanding borrows of the underlying in this market\"},\"totalBorrowsCurrent()\":{\"notice\":\"Returns the current total borrows plus accrued interest\"},\"totalReserves()\":{\"notice\":\"Total amount of reserves of the underlying held in this market\"},\"totalSupply()\":{\"notice\":\"Total number of tokens in circulation\"},\"transfer(address,uint256)\":{\"notice\":\"Transfer `amount` tokens from `msg.sender` to `dst`\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"Transfer `amount` tokens from `src` to `dst`\"},\"underlying()\":{\"notice\":\"Underlying asset for this VToken\"}},\"notice\":\"Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview, each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of the pool. The main actions a user regularly interacts with in a market are: - mint/redeem of vTokens; - transfer of vTokens; - borrow/repay a loan on an underlying asset; - liquidate a borrow or liquidate/heal an account. A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`. The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken` as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also pay off interest accrued on the borrow. The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller` and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`. Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/VToken.sol\":\"VToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"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/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.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\":\"0x4dae161227d332808312ee2caf6384929321b83c16cc89b5642985fbec6b814c\",\"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/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/protocol-reserve/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/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor is changed by admin\\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive is changed by admin\\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow.\\n * @param vTokenAddress The address of the asset to be removed\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return NO_ERROR;\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\n _checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = accountAssets[user];\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = accountAssets[borrower];\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\n // Set liquidation incentive to new incentive\\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n // Emit event with old incentive, new incentive\\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n _ensureMaxLoops(numMarkets);\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Enables forced liquidations for a market. If forced liquidation is enabled,\\n * borrows in the market may be liquidated regardless of the account liquidity\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall Hypothetical account shortfall below collateral requirements\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market.\\n * @return markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Check if a market is marked as listed (active)\\n * @param vToken vToken Address for the market to check\\n * @return listed True if listed otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].isListed;\\n }\\n\\n /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns the assets an account has entered\\n * @param account The address of the account to pull assets for\\n * @return A list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n VToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the market specified, otherwise false.\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return markets[address(vToken)].accountMembership[account];\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = accountAssets[account];\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\n\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n }\\n\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = accountAssets[account];\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x42f9cceba5f1b4d82047f930a7049740d13ab36004bb1a58b462b9e111c08665\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x44c67531518072db11bf6eafe29499073724346a7855579b09a9da049742d879\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // Multiplier representing the most one can borrow against their collateral in this market.\\n // For instance, 0.9 to allow borrowing 90% of collateral value.\\n // Must be between 0 and 1, and stored as a mantissa.\\n uint256 collateralFactorMantissa;\\n // Multiplier representing the collateralization after which the borrow is eligible\\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n // value. Must be between 0 and collateral factor, stored as a mantissa.\\n uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\n enum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n }\\n\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives\\n */\\n uint256 public liquidationIncentiveMantissa;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n /**\\n * @notice Official mapping of vTokens -> Market metadata\\n * @dev Used e.g. to determine if a market is supported\\n */\\n mapping(address => Market) public markets;\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\\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\":\"0xdfc033911c20e09516110ae3f94740b4be1a065baee4412a708e25a25568eac8\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x3f8ec4e18bca1fdf8619966f4f6e095e205517a78f8c741b87fe82125754f96f\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x1f17b8e3fdd89657d488250140f6d6abeb04f2b822467139687487f9c1dbe397\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x60ea8b0b70165acc3cf0f1e92f8dcea93ef5ddc2b8b99172799594aeec7c22b5\",\"license\":\"BSD-3-Clause\"},\"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\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each block for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller private comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlock(address[],uint32[],uint32[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumber();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\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 */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumber = getBlockNumber();\\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumber;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n function getBlockNumber() public view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumber();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplyIndex = supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowIndex = borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\\n blockNumber = supplyState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\\n\\n if (deltaBlocks > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n supplyState.index = safe224(\\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n supplyState.block = blockNumber;\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint32 blockNumber = safe32(getBlockNumber(), \\\"block number exceeds 32 bits\\\");\\n\\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\\n blockNumber = borrowState.lastRewardingBlock;\\n }\\n\\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\\n if (deltaBlocks > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n borrowState.index = safe224(\\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks > 0) {\\n borrowState.block = blockNumber;\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0x598aad1a12d6a895f82a8b619000099efe53994fe89522b41adaa68819fac652\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.13;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n /**\\n * Reentrancy Guard **\\n */\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\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 /**\\n * @notice Construct a new money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\n );\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\\n _redeemFresh(msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n _borrowFresh(msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to borrower\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n * @dev Admin function to accrue interest and set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == _getBlockNumber()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\n }\\n\\n /**\\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Admin function to accrue interest and update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockDelta block difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockDelta;\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return amount The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return rate The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this v\\n * @return rate The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number */\\n uint256 currentBlockNumber = _getBlockNumber();\\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentBlockNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n _reduceReservesFresh(totalReservesNew);\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is sending the assets for supply\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `_doTransferIn` for the minter and the mintAmount.\\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n }\\n\\n /**\\n * @notice User redeems vTokens in exchange for the underlying asset\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n */\\n function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\\n * On success, the vToken has redeemAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(redeemer, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n }\\n\\n /**\\n * @notice Users borrow assets from the protocol to their own address\\n * @param borrower User who borrows the assets\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the borrower and the borrowAmount.\\n * On success, the vToken borrowAmount less of cash.\\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n _doTransferOut(borrower, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the borrow\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call _doTransferIn for the payer and the repayAmount\\n * On success, the vToken holds an additional repayAmount of cash.\\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == NO_ERROR, \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != _getBlockNumber()) {\\n revert SetInterestRateModelFreshCheck();\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n }\\n\\n /**\\n * Safe Token **\\n */\\n\\n /**\\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\\n * This function returns the actual amount received,\\n * which may be less than `amount` if there is a fee attached to the transfer.\\n * @param from Sender of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n * @return Actual amount received\\n */\\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n // Return the amount that was *actually* transferred\\n return balanceAfter - balanceBefore;\\n }\\n\\n /**\\n * @dev Just a regular ERC-20 transfer, reverts on failure\\n * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n _setComptroller(comptroller_);\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = _getBlockNumber();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying tokens owned by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\n }\\n\\n /**\\n * @dev Function to simply retrieve block number\\n * This exists mainly for inheriting test contracts to stub this result.\\n * @return Current block number\\n */\\n function _getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xf4f49f4a1718a36a7cbd413e959d957eade62d4ad96c0ebde4562e53cac72f7e\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\n\\n // Maximum borrow rate that can ever be applied (.0005% / block)\\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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[48] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves block delta is changed\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x777842977e2441dd79f4781ff61f431dda351c3d33862e40063ef58d03b489a1\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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\",\"keccak256\":\"0x44de02d7837ee1d4dcf6e9f5e783e9d9e0bec0154f23f5661fb54810cff9f892\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x909eb76841ebd57d8f53686b76b1a09da7bbbbcddb29510c41674d5aa84c713e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61487c80620000f36000396000f3fe608060405234801561001057600080fd5b50600436106103f15760003560e01c8063757212f011610215578063ae9d70b011610125578063db006a75116100b8578063ef60450c11610087578063ef60450c14610861578063f2fde38b14610874578063f3fdb15a14610887578063f5e3c4621461089a578063f8f9da28146108ad57600080fd5b8063db006a75146107ec578063dd62ed3e146107ff578063e30c397814610838578063e9a44fd91461084957600080fd5b8063bd6d894d116100f4578063bd6d894d14610795578063c37f68e21461079d578063c5ebeaec146107d0578063d1109c2f146107e357600080fd5b8063ae9d70b014610760578063b2a02ff114610768578063b4a0bdf31461077b578063bbcac5571461078c57600080fd5b80638f840ddd116101a8578063a457c2d711610177578063a457c2d714610720578063a6afed9514610733578063a9059cbb1461073b578063aa5af0fd1461074e578063ae96f1411461075757600080fd5b80638f840ddd146106e957806395d89b41146106f257806395dd9193146106fa578063a0712d681461070d57600080fd5b80638a42c319116101e45780638a42c3191461069f5780638bbdb6db146106b25780638bcd4016146106c55780638da5cb5b146106d857600080fd5b8063757212f01461065e5780637821a5141461067157806379ba509714610684578063852a12e31461068c57600080fd5b80632608f8181161031057806347bd3718116102a35780636c540baf116102725780636c540baf146106045780636f307dc31461060d57806370a0823114610625578063715018a61461064e57806373acee981461065657600080fd5b806347bd3718146105d75780635fe3b567146105e05780636752e702146105f357806369ab3250146105fc57600080fd5b80633b1d21a2116102df5780633b1d21a2146105a25780633d9ea3a1146105aa57806341f641ee146105b157806344fe6ffe146105c457600080fd5b80632608f8181461054a578063313ce5671461055d578063395093511461057c5780633af9e6691461058f57600080fd5b806318160ddd116103885780631c446983116103575780631c446983146104fe57806323323e031461051157806323b872dd146105245780632464176b1461053757600080fd5b806318160ddd146104af578063182df0f5146104b857806319b1faef146104c05780631be19560146104eb57600080fd5b80630e752702116103c45780630e7527021461045f578063107568df14610480578063173b99041461049357806317bfdfbc1461049c57600080fd5b806306fdde03146103f657806307e2795914610414578063095ea7b3146104295780630e32cb861461044c575b600080fd5b6103fe6108b5565b60405161040b91906141b6565b60405180910390f35b6104276104223660046141c9565b610943565b005b61043c610437366004614207565b6109a3565b604051901515815260200161040b565b61042761045a366004614233565b610a12565b61047261046d3660046141c9565b610a26565b60405190815260200161040b565b61042761048e366004614233565b610a80565b61047260d05481565b6104726104aa366004614233565b610a91565b61047260d55481565b610472610ae6565b60db546104d3906001600160a01b031681565b6040516001600160a01b03909116815260200161040b565b6104276104f9366004614233565b610af5565b61042761050c3660046141c9565b610cb0565b61047261051f366004614207565b610d2b565b61043c610532366004614250565b610d8d565b6104276105453660046141c9565b610ddf565b610472610558366004614207565b610e81565b60cc5461056a9060ff1681565b60405160ff909116815260200161040b565b61043c61058a366004614207565b610edc565b61047261059d366004614233565b610f84565b610472610fca565b600161043c565b6104276105bf366004614233565b610fd4565b6104276105d2366004614250565b610fe5565b61047260d35481565b60cd546104d3906001600160a01b031681565b61047260da5481565b610472600081565b61047260d15481565b60c9546104d39061010090046001600160a01b031681565b610472610633366004614233565b6001600160a01b0316600090815260d7602052604090205490565b610427611288565b61047261129c565b61042761066c3660046141c9565b6112e8565b61042761067f3660046141c9565b61140f565b61042761145e565b61047261069a3660046141c9565b6114d5565b6104276106ad3660046143a8565b61152e565b6104276106c03660046144a9565b61165e565b6104276106d3366004614233565b61169d565b6033546001600160a01b03166104d3565b61047260d45481565b6103fe6116ed565b610472610708366004614233565b6116fa565b61047261071b3660046141c9565b61170b565b61043c61072e366004614207565b61174e565b61047261182b565b61043c610749366004614207565b611a47565b61047260d25481565b61047260dd5481565b610472611a98565b610427610776366004614250565b611b3b565b6097546001600160a01b03166104d3565b61047260d65481565b610472611b85565b6107b06107ab366004614233565b611bd7565b60408051948552602085019390935291830152606082015260800161040b565b6104726107de3660046141c9565b611c18565b61047260dc5481565b6104726107fa3660046141c9565b611c5a565b61047261080d366004614511565b6001600160a01b03918216600090815260d86020908152604080832093909416825291909152205490565b6065546001600160a01b03166104d3565b60cc546104d39061010090046001600160a01b031681565b61042761086f3660046141c9565b611c9e565b610427610882366004614233565b611dbd565b60ce546104d3906001600160a01b031681565b6104726108a836600461454a565b611e2e565b610472611e48565b60ca80546108c29061458c565b80601f01602080910402602001604051908101604052809291908181526020018280546108ee9061458c565b801561093b5780601f106109105761010080835404028352916020019161093b565b820191906000526020600020905b81548152906001019060200180831161091e57829003601f168201915b505050505081565b60c95460ff1661096e5760405162461bcd60e51b8152600401610965906145c6565b60405180910390fd5b60c9805460ff1916905561098061182b565b504360dd54146109935761099381611ea3565b5060c9805460ff19166001179055565b60006109ae83612018565b33600081815260d8602090815260408083206001600160a01b038816808552908352928190208690555185815283917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060019392505050565b610a1a61203f565b610a2381612099565b50565b60c95460009060ff16610a4b5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610a5d61182b565b50610a6933338461215f565b506000905060c9805460ff19166001179055919050565b610a8861203f565b610a23816122bb565b60c95460009060ff16610ab65760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610ac861182b565b50610ad28261231e565b905060c9805460ff19166001179055919050565b6000610af061238e565b905090565b6033546001600160a01b03163314610b675760405162461bcd60e51b815260206004820152602f60248201527f56546f6b656e3a3a7377656570546f6b656e3a206f6e6c792061646d696e206360448201526e616e20737765657020746f6b656e7360881b6064820152608401610965565b60c9546001600160a01b03610100909104811690821603610be55760405162461bcd60e51b815260206004820152603260248201527f56546f6b656e3a3a7377656570546f6b656e3a2063616e206e6f74207377656560448201527138103ab73232b9363cb4b733903a37b5b2b760711b6064820152608401610965565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5091906145ea565b9050610c78610c676033546001600160a01b031690565b6001600160a01b0384169083612403565b6040516001600160a01b038316907f35ce4c546a473796a8e70ec2d4af4f2031afe357afa7057b6ea7fa340730e1b290600090a25050565b60c95460ff16610cd25760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff1916905560408051808201909152601981527f73657452657365727665466163746f722875696e7432353629000000000000006020820152610d199061246b565b610d2161182b565b5061099381612509565b60c95460009060ff16610d505760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610d6383612018565b610d6b61182b565b50610d77338484612592565b50600060c9805460ff1916600117905592915050565b60c95460009060ff16610db25760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610dc833858585612723565b50600160c9805460ff191660011790559392505050565b610e006040518060600160405280602481526020016148036024913961246b565b60008111610e405760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908125b9c1d5d609a1b6044820152606401610965565b60dc5460408051918252602082018390527fc2ac513cdb57f91eb2bef4db918c285829524f549682b99717c6cb06cc011183910160405180910390a160dc55565b60c95460009060ff16610ea65760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610eb861182b565b50610ec433848461215f565b506000905060c9805460ff1916600117905592915050565b6000610ee783612018565b33600081815260d8602090815260408083206001600160a01b0388168452909152902054610f158482614619565b6001600160a01b03838116600081815260d860209081526040808320948b16808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3506001949350505050565b6000806040518060200160405280610f9a611b85565b90526001600160a01b038416600090815260d76020526040902054909150610fc3908290612910565b9392505050565b6000610af0612928565b610fdc61203f565b610a238161295e565b60c95460ff166110075760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055801561107d5760cd5460405163eade3eed60e01b81523060048201526001600160a01b0384811660248301529091169063eade3eed90604401600060405180830381600087803b15801561106457600080fd5b505af1158015611078573d6000803e3d6000fd5b505050505b60cd546001600160a01b031633146110a857604051632c40292560e01b815260040160405180910390fd5b60006110b38361231e565b60d35490915060008315611133576110cb86856129b9565b90506110d78183614631565b91506001600160a01b038086169087167f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1836111138188614631565b604080519283526020830191909152810186905260600160405180910390a35b600061113f8285614631565b905080156112075760d65460006111568383614619565b90506111628386614631565b60d682905560408051858152600060208201529081018290529095506001600160a01b0389169030907f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060600160405180910390a360408051848152602081018490529081018290526001600160a01b038916907f90125ffdb441e57c4f6bf69789206424859f206bea5727f2d81ad2470826ef6a9060600160405180910390a250505b6001600160a01b03808716600081815260d9602052604080822091825560d25460019092019190915560d38690555190918916907f9fe0294717a8efbc6ace1c151b73a4c89982339b2228a27d1ca21394e348986f9061126a9089815260200190565b60405180910390a3505060c9805460ff191660011790555050505050565b61129061203f565b61129a6000612ac7565b565b60c95460009060ff166112c15760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff191690556112d361182b565b505060d35460c9805460ff1916600117905590565b6113266040518060400160405280601e81526020017f73657450726f746f636f6c5365697a6553686172652875696e7432353629000081525061246b565b60cd5460408051634ada90af60e01b815290516000926001600160a01b031691634ada90af9160048083019260209291908290030181865afa158015611370573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139491906145ea565b9050806113a9670de0b6b3a764000084614619565b11156113c85760405163034dd2c160e11b815260040160405180910390fd5b60da80549083905560408051828152602081018590527ff5815f353a60e815cce7553e4f60c533a59d26b1b5504ea4b6db8d60da3e4da291015b60405180910390a1505050565b60c95460ff166114315760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff1916905561144361182b565b5061144d81612ae0565b505060c9805460ff19166001179055565b60655433906001600160a01b031681146114cc5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610965565b610a2381612ac7565b60c95460009060ff166114fa5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff1916905561150c61182b565b5061151933600084612b6d565b50600060c9805460ff19166001179055919050565b600054610100900460ff161580801561154e5750600054600160ff909116105b806115685750303b158015611568575060005460ff166001145b6115cb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610965565b6000805460ff1916600117905580156115ee576000805461ff0019166101001790555b6115f785612018565b61160a8c8c8c8c8c8c8c8c8c8c8c612e38565b8015611650576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b60cd546001600160a01b0316331461168957604051635c85a5e760e01b815260040160405180910390fd5b6116968585858585613079565b5050505050565b6116db6040518060400160405280601d81526020017f736574496e746572657374526174654d6f64656c28616464726573732900000081525061246b565b6116e361182b565b50610a238161315a565b60cb80546108c29061458c565b60006117058261231e565b92915050565b60c95460009060ff166117305760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff1916905561174261182b565b50611519333384612592565b600061175983612018565b33600081815260d8602090815260408083206001600160a01b0388168452909152902054838110156117cd5760405162461bcd60e51b815260206004820152601e60248201527f64656372656173656420616c6c6f77616e63652062656c6f77207a65726f00006044820152606401610965565b6001600160a01b03828116600081815260d860209081526040808320948a1680845294825291829020948890039485905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259101610f71565b60d15460009043908181036118435760009250505090565b600061184d612928565b60d35460d45460d25460ce5460d6546040516301cee29d60e21b815260048101879052602481018690526044810185905260648101919091529495509293919290916000916001600160a01b03169063073b8a7490608401602060405180830381865afa1580156118c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e691906145ea565b905065048c2739500081111561193e5760405162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c792068696768000000006044820152606401610965565b600061194a8789614631565b9050600061196660405180602001604052808581525083613295565b905060006119748288612910565b905060006119828883614619565b905060006119a1604051806020016040528060d054815250848a6132c6565b905060006119b085898a6132c6565b60d18e905560d281905560d384905560d483905560dc5460dd54919250906119d8908f614631565b106119eb5760dd8d90556119eb82611ea3565b604080518c815260208101869052908101829052606081018490527f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc049060800160405180910390a160009d505050505050505050505050505090565b60c95460009060ff16611a6c5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611a8233808585612723565b50600160c9805460ff1916600117905592915050565b60ce546000906001600160a01b0316630cde8d1c611ab4612928565b60d35460d45460d05460d6546040516001600160e01b031960e088901b1681526004810195909552602485019390935260448401919091526064830152608482015260a4015b602060405180830381865afa158015611b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af091906145ea565b60c95460ff16611b5d5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611b73338484846132e7565b505060c9805460ff1916600117905550565b60c95460009060ff16611baa5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611bbc61182b565b50611bc561238e565b905060c9805460ff1916600117905590565b6001600160a01b038116600090815260d760205260408120548190819081908190611c018761231e565b611c0961238e565b93509350935093509193509193565b60c95460009060ff16611c3d5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611c4f61182b565b506115193383613615565b60c95460009060ff16611c7f5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611c9161182b565b5061151933836000612b6d565b60db546001600160a01b03163314611d0c5760405162461bcd60e51b815260206004820152602b60248201527f6f6e6c792073686f727466616c6c20636f6e74726163742063616e207570646160448201526a1d1948189859081919589d60aa1b6064820152608401610965565b60d654811115611d705760405162461bcd60e51b815260206004820152602960248201527f6d6f7265207468616e206261642064656274207265636f76657265642066726f604482015268369030bab1ba34b7b760b91b6064820152608401610965565b60d6546000611d7f8383614631565b60d681905560408051848152602081018390529192507f9e19ec7d2b8f8a94df8cc0072453ace318d221e3cbb2731d0eaa0baac856520f9101611402565b611dc561203f565b606580546001600160a01b0383166001600160a01b03199091168117909155611df66033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000611e3e338585856000613079565b5060009392505050565b60ce546000906001600160a01b031663073b8a74611e64612928565b60d35460d45460d6546040516001600160e01b031960e087901b1681526004810194909452602484019290925260448301526064820152608401611afa565b80600003611eae5750565b60004360d15414611ed257604051630dff50cb60e41b815260040160405180910390fd5b81611edb612928565b1015611efa57604051633345e99960e01b815260040160405180910390fd5b60d454821115611f1d576040516378d2980560e11b815260040160405180910390fd5b8160d454611f2b9190614631565b60d481905560cc54909150611f4e9061010090046001600160a01b03168361378b565b60cc5460cd5460c9546040516305bebb3b60e21b81526001600160a01b03610100948590048116946316faecec94611f96949083169391900490911690600090600401614648565b600060405180830381600087803b158015611fb057600080fd5b505af1158015611fc4573d6000803e3d6000fd5b505060cc5460408051868152602081018690526101009092046001600160a01b031693507f9cc63bb4ef37ad6a5f5f657dfaf94865531d4234acbc431cc8ac035468f6272092500160405180910390a25050565b6001600160a01b038116610a23576040516342bcdf7f60e11b815260040160405180910390fd5b6033546001600160a01b0316331461129a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610965565b6001600160a01b0381166120fd5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610965565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091015b60405180910390a15050565b60cd5460405163eade3eed60e01b81523060048201526001600160a01b038481166024830152600092169063eade3eed90604401600060405180830381600087803b1580156121ad57600080fd5b505af11580156121c1573d6000803e3d6000fd5b505050506121cc4390565b60d154146121ed5760405163c9021e2f60e01b815260040160405180910390fd5b60006121f88461231e565b905060008184101561220a578361220c565b815b9050600061221a87836129b9565b905060006122288285614631565b905060008260d35461223a9190614631565b6001600160a01b03898116600081815260d9602090815260409182902087815560d25460019091015560d3859055815188815290810187905290810184905292935091908b16907f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060600160405180910390a35090979650505050505050565b6122c481612018565b60cc80546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907fafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b90600090a35050565b6001600160a01b038116600090815260d96020908152604080832081518083019092528054808352600190910154928201929092529082036123635750600092915050565b60d25481516000916123749161468c565b905081602001518161238691906146ab565b949350505050565b60d5546000908082036123a357505060cf5490565b60006123ad612928565b9050600060d45460d65460d354846123c59190614619565b6123cf9190614619565b6123d99190614631565b90506000836123f0670de0b6b3a76400008461468c565b6123fa91906146ab565b95945050505050565b6040516001600160a01b03831660248201526044810182905261246690849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526137a7565b505050565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab9061249e90339086906004016146cd565b602060405180830381865afa1580156124bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124df91906146f1565b90508061250557333083604051634a3fa29360e01b81526004016109659392919061470e565b5050565b4360d1541461252b57604051637dfca6b760e11b815260040160405180910390fd5b670de0b6b3a76400008111156125545760405163717220f360e11b815260040160405180910390fd5b60d080549082905560408051828152602081018490527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101612153565b60cd5460405163c0891ba960e01b81526001600160a01b039091169063c0891ba9906125c69030908690869060040161473a565b600060405180830381600087803b1580156125e057600080fd5b505af11580156125f4573d6000803e3d6000fd5b505050506125ff4390565b60d15414612620576040516338d8859760e01b815260040160405180910390fd5b6000604051806020016040528061263561238e565b90529050600061264585846129b9565b90506000612653828461387c565b90508060d5546126639190614619565b60d5556001600160a01b038516600090815260d7602052604081205461268a908390614619565b6001600160a01b038716600081815260d760209081526040918290208490558151878152908101869052908101839052919250907fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb9060600160405180910390a26040518281526001600160a01b038716906000906000805160206148278339815191529060200160405180910390a350505050505050565b60cd54604051636d0be88d60e01b81523060048201526001600160a01b03858116602483015284811660448301526064820184905290911690636d0be88d90608401600060405180830381600087803b15801561277f57600080fd5b505af1158015612793573d6000803e3d6000fd5b50505050816001600160a01b0316836001600160a01b0316036127c957604051638cd22d1960e01b815260040160405180910390fd5b6000836001600160a01b0316856001600160a01b0316036127ed5750600019612815565b506001600160a01b03808416600090815260d860209081526040808320938816835292905220545b60006128218383614631565b6001600160a01b038616600090815260d7602052604081205491925090612849908590614631565b6001600160a01b038616600090815260d7602052604081205491925090612871908690614619565b6001600160a01b03808916600090815260d76020526040808220869055918916815220819055905060001984146128cb576001600160a01b03808816600090815260d860209081526040808320938c168352929052208390555b856001600160a01b0316876001600160a01b0316600080516020614827833981519152876040516128fe91815260200190565b60405180910390a35050505050505050565b60008061291d8484613295565b90506123868161389a565b60c9546040516370a0823160e01b815230600482015260009161010090046001600160a01b0316906370a0823190602401611afa565b61296781612018565b60db80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef90600090a35050565b60c9546040516370a0823160e01b815230600482015260009161010090046001600160a01b031690829082906370a0823190602401602060405180830381865afa158015612a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2f91906145ea565b9050612a466001600160a01b0383168630876138b2565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015612a8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ab191906145ea565b9050612abd8282614631565b9695505050505050565b606580546001600160a01b0319169055610a23816138d9565b600080804360d15414612b09576040516338acf79960e01b815260048101829052602401610965565b612b1333856129b9565b90508060d454612b239190614619565b60d4819055604080518381526020810183905291935033917fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5910160405180910390a29392505050565b811580612b78575080155b612be15760405162461bcd60e51b815260206004820152603460248201527f6f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416044820152736d6f756e74496e206d757374206265207a65726f60601b6064820152608401610965565b4360d15414612c03576040516397b5cfcd60e01b815260040160405180910390fd5b60006040518060200160405280612c1861238e565b905290506000808415612c2d57849150612c6b565b612c37848461387c565b91506000612c45838561392b565b90508015801590612c565750848114155b15612c695782612c658161475e565b9350505b505b612c758383612910565b905080600003612cbe5760405162461bcd60e51b815260206004820152601460248201527372656465656d416d6f756e74206973207a65726f60601b6044820152606401610965565b60cd54604051634732387560e11b81526001600160a01b0390911690638e6470ea90612cf29030908a90879060040161473a565b600060405180830381600087803b158015612d0c57600080fd5b505af1158015612d20573d6000803e3d6000fd5b505050508060d454612d30612928565b612d3a9190614631565b1015612d59576040516391240a1b60e01b815260040160405180910390fd5b8160d554612d679190614631565b60d5556001600160a01b038616600090815260d76020526040812054612d8e908490614631565b6001600160a01b038816600090815260d7602052604090208190559050612db5878361378b565b60405183815230906001600160a01b038916906000805160206148278339815191529060200160405180910390a360408051838152602081018590529081018290526001600160a01b038816907fbd5034ffbd47e4e72a94baa2cdb74c6fad73cb3bcdc13036b72ec8306f5a76469060600160405180910390a250505050505050565b600054610100900460ff16612e5f5760405162461bcd60e51b815260040161096590614777565b612e6761394e565b612e708361397d565b60d154158015612e80575060d254155b612ed85760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b6064820152608401610965565b60cf88905587612f435760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b6064820152608401610965565b612f4c8a6139a4565b4360d155670de0b6b3a764000060d255612f658961315a565b612f6e81612509565b8651612f819060ca9060208a01906140c5565b508551612f959060cb9060208901906140c5565b5060cc805460ff191660ff87161790558151612fb09061295e565b612fbd82602001516122bb565b66b1a2bc2ec5000060da5560c98054610100600160a81b0319166101006001600160a01b038e811682029290921792839055604080516318160ddd60e01b8152905191909304909116916318160ddd9160048083019260209291908290030181865afa158015613031573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061305591906145ea565b5060c9805460ff1916600117905561306c84612ac7565b5050505050505050505050565b60c95460ff1661309b5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff191690556130ad61182b565b506000826001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156130f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061311491906145ea565b9050801561313857604051633eea49b760e11b815260048101829052602401610965565b6131458686868686613aaf565b505060c9805460ff1916600117905550505050565b60004360d1541461317e57604051630be2a5cb60e11b815260040160405180910390fd5b60ce60009054906101000a90046001600160a01b03169050816001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f891906146f1565b6132445760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401610965565b60ce80546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f92690600090a35050565b60408051602081019091526000815260405180602001604052806132bd856000015185613ee9565b90529392505050565b6000806132d38585613295565b90506123fa6132e18261389a565b84613ef5565b60cd5460405163037883e560e31b81523060048201526001600160a01b0386811660248301528581166044830152848116606483015290911690631bc41f2890608401600060405180830381600087803b15801561334457600080fd5b505af1158015613358573d6000803e3d6000fd5b50505050826001600160a01b0316826001600160a01b03160361338e57604051633a94626760e11b815260040160405180910390fd5b60cd5460408051634ada90af60e01b815290516000926001600160a01b031691634ada90af9160048083019260209291908290030181865afa1580156133d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133fc91906145ea565b9050600061341a83604051806020016040528060da5481525061392b565b905060006134368260405180602001604052808681525061387c565b905060006134448286614631565b90506000604051806020016040528061345b61238e565b90529050600061346b8285612910565b90508360d55461347b9190614631565b60d5556001600160a01b038816600090815260d760205260409020546134a2908890614631565b6001600160a01b03808a16600090815260d7602052604080822093909355908b16815220546134d2908490614619565b6001600160a01b03808b16600090815260d7602052604090209190915560cc5461350391610100909104168261378b565b60cc5460cd5460c9546040516305bebb3b60e21b81526001600160a01b03610100948590048116946316faecec9461354b949083169391900490911690600190600401614648565b600060405180830381600087803b15801561356557600080fd5b505af1158015613579573d6000803e3d6000fd5b50505050886001600160a01b0316886001600160a01b0316600080516020614827833981519152856040516135b091815260200190565b60405180910390a360cc546040516001600160a01b036101009092048216918a16907f3ac0548d62d3fa3c9a817cd33899b9acacd57e8958ebe51bc7d9a79f26a8a5db906136019085815260200190565b60405180910390a350505050505050505050565b60cd5460405163df71403b60e01b81526001600160a01b039091169063df71403b906136499030908690869060040161473a565b600060405180830381600087803b15801561366357600080fd5b505af1158015613677573d6000803e3d6000fd5b505050506136824390565b60d154146136a357604051630e8d8c6160e21b815260040160405180910390fd5b8060d4546136af612928565b6136b99190614631565b10156136d8576040516348c2588160e01b815260040160405180910390fd5b60006136e38361231e565b905060006136f18383614619565b905060008360d3546137039190614619565b6001600160a01b038616600090815260d96020526040902083815560d25460019091015560d38190559050613738858561378b565b60408051858152602081018490529081018290526001600160a01b038616907f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060600160405180910390a25050505050565b60c95461010090046001600160a01b0316612466818484612403565b60006137fc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613f019092919063ffffffff16565b905080516000148061381d57508080602001905181019061381d91906146f1565b6124665760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610965565b6000610fc361389384670de0b6b3a7640000613ee9565b8351613f10565b805160009061170590670de0b6b3a7640000906146ab565b6138d3846323b872dd60e01b85858560405160240161242f9392919061473a565b50505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000670de0b6b3a7640000613944848460000151613ee9565b610fc391906146ab565b600054610100900460ff166139755760405162461bcd60e51b815260040161096590614777565b61129a613f1c565b600054610100900460ff16610a1a5760405162461bcd60e51b815260040161096590614777565b60cd5460408051623f1ee960e11b815290516001600160a01b0392831692841691627e3dd29160048083019260209291908290030181865afa1580156139ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a1291906146f1565b613a5e5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401610965565b60cd80546001600160a01b0319166001600160a01b0384811691821790925560405190918316907f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d90600090a35050565b60cd5460405163e89d51ad60e01b81523060048201526001600160a01b03848116602483015286811660448301526064820186905283151560848301529091169063e89d51ad9060a401600060405180830381600087803b158015613b1357600080fd5b505af1158015613b27573d6000803e3d6000fd5b50505050613b324390565b60d15414613b53576040516380965b1b60e01b815260040160405180910390fd5b43826001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb691906145ea565b14613bd457604051631046f38d60e31b815260040160405180910390fd5b846001600160a01b0316846001600160a01b031603613c0657604051631bd1a62160e21b815260040160405180910390fd5b82600003613c275760405163d29da7ef60e01b815260040160405180910390fd5b6000198303613c4957604051635982c5bb60e11b815260040160405180910390fd5b6000613c5686868661215f565b60cd5460405163c488847b60e01b815291925060009182916001600160a01b03169063c488847b90613c909030908990889060040161473a565b6040805180830381865afa158015613cac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cd091906147c2565b9150915060008214613d405760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b6064820152608401610965565b6040516370a0823160e01b81526001600160a01b0388811660048301528291908716906370a0823190602401602060405180830381865afa158015613d89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dad91906145ea565b1015613dfb5760405162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d55434800000000000000006044820152606401610965565b306001600160a01b03861603613e1c57613e17308989846132e7565b613e7f565b60405163b2a02ff160e01b81526001600160a01b0386169063b2a02ff190613e4c908b908b90869060040161473a565b600060405180830381600087803b158015613e6657600080fd5b505af1158015613e7a573d6000803e3d6000fd5b505050505b846001600160a01b0316876001600160a01b0316896001600160a01b03167f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb528685604051613ed7929190918252602082015260400190565b60405180910390a45050505050505050565b6000610fc3828461468c565b6000610fc38284614619565b60606123868484600085613f4c565b6000610fc382846146ab565b600054610100900460ff16613f435760405162461bcd60e51b815260040161096590614777565b61129a33612ac7565b606082471015613fad5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610965565b600080866001600160a01b03168587604051613fc991906147e6565b60006040518083038185875af1925050503d8060008114614006576040519150601f19603f3d011682016040523d82523d6000602084013e61400b565b606091505b509150915061401c87838387614027565b979650505050505050565b6060831561409657825160000361408f576001600160a01b0385163b61408f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610965565b5081612386565b61238683838151156140ab5781518083602001fd5b8060405162461bcd60e51b815260040161096591906141b6565b8280546140d19061458c565b90600052602060002090601f0160209004810192826140f35760008555614139565b82601f1061410c57805160ff1916838001178555614139565b82800160010185558215614139579182015b8281111561413957825182559160200191906001019061411e565b50614145929150614149565b5090565b5b80821115614145576000815560010161414a565b60005b83811015614179578181015183820152602001614161565b838111156138d35750506000910152565b600081518084526141a281602086016020860161415e565b601f01601f19169290920160200192915050565b602081526000610fc3602083018461418a565b6000602082840312156141db57600080fd5b5035919050565b6001600160a01b0381168114610a2357600080fd5b8035614202816141e2565b919050565b6000806040838503121561421a57600080fd5b8235614225816141e2565b946020939093013593505050565b60006020828403121561424557600080fd5b8135610fc3816141e2565b60008060006060848603121561426557600080fd5b8335614270816141e2565b92506020840135614280816141e2565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126142b857600080fd5b813567ffffffffffffffff808211156142d3576142d3614291565b604051601f8301601f19908116603f011681019082821181831017156142fb576142fb614291565b8160405283815286602085880101111561431457600080fd5b836020870160208301376000602085830101528094505050505092915050565b803560ff8116811461420257600080fd5b60006040828403121561435757600080fd5b6040516040810181811067ffffffffffffffff8211171561437a5761437a614291565b604052905080823561438b816141e2565b8152602083013561439b816141e2565b6020919091015292915050565b60008060008060008060008060008060006101808c8e0312156143ca57600080fd5b6143d38c6141f7565b9a506143e160208d016141f7565b99506143ef60408d016141f7565b985060608c0135975067ffffffffffffffff8060808e0135111561441257600080fd5b6144228e60808f01358f016142a7565b97508060a08e0135111561443557600080fd5b506144468d60a08e01358e016142a7565b955061445460c08d01614334565b945061446260e08d016141f7565b93506144716101008d016141f7565b92506144818d6101208e01614345565b91506101608c013590509295989b509295989b9093969950565b8015158114610a2357600080fd5b600080600080600060a086880312156144c157600080fd5b85356144cc816141e2565b945060208601356144dc816141e2565b93506040860135925060608601356144f3816141e2565b915060808601356145038161449b565b809150509295509295909350565b6000806040838503121561452457600080fd5b823561452f816141e2565b9150602083013561453f816141e2565b809150509250929050565b60008060006060848603121561455f57600080fd5b833561456a816141e2565b9250602084013591506040840135614581816141e2565b809150509250925092565b600181811c908216806145a057607f821691505b6020821081036145c057634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b6000602082840312156145fc57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561462c5761462c614603565b500190565b60008282101561464357614643614603565b500390565b6001600160a01b03848116825283166020820152606081016002831061467e57634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b60008160001904831182151516156146a6576146a6614603565b500290565b6000826146c857634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b03831681526040602082018190526000906123869083018461418a565b60006020828403121561470357600080fd5b8151610fc38161449b565b6001600160a01b038481168252831660208201526060604082018190526000906123fa9083018461418a565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001820161477057614770614603565b5060010190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600080604083850312156147d557600080fd5b505080516020909101519092909150565b600082516147f881846020870161415e565b919091019291505056fe7365745265647563655265736572766573426c6f636b44656c74612875696e7432353629ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220ce57b3aa2fd5fc240f24aa84c4d021e7ab68ec84ae7ae60fdb58968caec6e1cb64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106103f15760003560e01c8063757212f011610215578063ae9d70b011610125578063db006a75116100b8578063ef60450c11610087578063ef60450c14610861578063f2fde38b14610874578063f3fdb15a14610887578063f5e3c4621461089a578063f8f9da28146108ad57600080fd5b8063db006a75146107ec578063dd62ed3e146107ff578063e30c397814610838578063e9a44fd91461084957600080fd5b8063bd6d894d116100f4578063bd6d894d14610795578063c37f68e21461079d578063c5ebeaec146107d0578063d1109c2f146107e357600080fd5b8063ae9d70b014610760578063b2a02ff114610768578063b4a0bdf31461077b578063bbcac5571461078c57600080fd5b80638f840ddd116101a8578063a457c2d711610177578063a457c2d714610720578063a6afed9514610733578063a9059cbb1461073b578063aa5af0fd1461074e578063ae96f1411461075757600080fd5b80638f840ddd146106e957806395d89b41146106f257806395dd9193146106fa578063a0712d681461070d57600080fd5b80638a42c319116101e45780638a42c3191461069f5780638bbdb6db146106b25780638bcd4016146106c55780638da5cb5b146106d857600080fd5b8063757212f01461065e5780637821a5141461067157806379ba509714610684578063852a12e31461068c57600080fd5b80632608f8181161031057806347bd3718116102a35780636c540baf116102725780636c540baf146106045780636f307dc31461060d57806370a0823114610625578063715018a61461064e57806373acee981461065657600080fd5b806347bd3718146105d75780635fe3b567146105e05780636752e702146105f357806369ab3250146105fc57600080fd5b80633b1d21a2116102df5780633b1d21a2146105a25780633d9ea3a1146105aa57806341f641ee146105b157806344fe6ffe146105c457600080fd5b80632608f8181461054a578063313ce5671461055d578063395093511461057c5780633af9e6691461058f57600080fd5b806318160ddd116103885780631c446983116103575780631c446983146104fe57806323323e031461051157806323b872dd146105245780632464176b1461053757600080fd5b806318160ddd146104af578063182df0f5146104b857806319b1faef146104c05780631be19560146104eb57600080fd5b80630e752702116103c45780630e7527021461045f578063107568df14610480578063173b99041461049357806317bfdfbc1461049c57600080fd5b806306fdde03146103f657806307e2795914610414578063095ea7b3146104295780630e32cb861461044c575b600080fd5b6103fe6108b5565b60405161040b91906141b6565b60405180910390f35b6104276104223660046141c9565b610943565b005b61043c610437366004614207565b6109a3565b604051901515815260200161040b565b61042761045a366004614233565b610a12565b61047261046d3660046141c9565b610a26565b60405190815260200161040b565b61042761048e366004614233565b610a80565b61047260d05481565b6104726104aa366004614233565b610a91565b61047260d55481565b610472610ae6565b60db546104d3906001600160a01b031681565b6040516001600160a01b03909116815260200161040b565b6104276104f9366004614233565b610af5565b61042761050c3660046141c9565b610cb0565b61047261051f366004614207565b610d2b565b61043c610532366004614250565b610d8d565b6104276105453660046141c9565b610ddf565b610472610558366004614207565b610e81565b60cc5461056a9060ff1681565b60405160ff909116815260200161040b565b61043c61058a366004614207565b610edc565b61047261059d366004614233565b610f84565b610472610fca565b600161043c565b6104276105bf366004614233565b610fd4565b6104276105d2366004614250565b610fe5565b61047260d35481565b60cd546104d3906001600160a01b031681565b61047260da5481565b610472600081565b61047260d15481565b60c9546104d39061010090046001600160a01b031681565b610472610633366004614233565b6001600160a01b0316600090815260d7602052604090205490565b610427611288565b61047261129c565b61042761066c3660046141c9565b6112e8565b61042761067f3660046141c9565b61140f565b61042761145e565b61047261069a3660046141c9565b6114d5565b6104276106ad3660046143a8565b61152e565b6104276106c03660046144a9565b61165e565b6104276106d3366004614233565b61169d565b6033546001600160a01b03166104d3565b61047260d45481565b6103fe6116ed565b610472610708366004614233565b6116fa565b61047261071b3660046141c9565b61170b565b61043c61072e366004614207565b61174e565b61047261182b565b61043c610749366004614207565b611a47565b61047260d25481565b61047260dd5481565b610472611a98565b610427610776366004614250565b611b3b565b6097546001600160a01b03166104d3565b61047260d65481565b610472611b85565b6107b06107ab366004614233565b611bd7565b60408051948552602085019390935291830152606082015260800161040b565b6104726107de3660046141c9565b611c18565b61047260dc5481565b6104726107fa3660046141c9565b611c5a565b61047261080d366004614511565b6001600160a01b03918216600090815260d86020908152604080832093909416825291909152205490565b6065546001600160a01b03166104d3565b60cc546104d39061010090046001600160a01b031681565b61042761086f3660046141c9565b611c9e565b610427610882366004614233565b611dbd565b60ce546104d3906001600160a01b031681565b6104726108a836600461454a565b611e2e565b610472611e48565b60ca80546108c29061458c565b80601f01602080910402602001604051908101604052809291908181526020018280546108ee9061458c565b801561093b5780601f106109105761010080835404028352916020019161093b565b820191906000526020600020905b81548152906001019060200180831161091e57829003601f168201915b505050505081565b60c95460ff1661096e5760405162461bcd60e51b8152600401610965906145c6565b60405180910390fd5b60c9805460ff1916905561098061182b565b504360dd54146109935761099381611ea3565b5060c9805460ff19166001179055565b60006109ae83612018565b33600081815260d8602090815260408083206001600160a01b038816808552908352928190208690555185815283917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060019392505050565b610a1a61203f565b610a2381612099565b50565b60c95460009060ff16610a4b5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610a5d61182b565b50610a6933338461215f565b506000905060c9805460ff19166001179055919050565b610a8861203f565b610a23816122bb565b60c95460009060ff16610ab65760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610ac861182b565b50610ad28261231e565b905060c9805460ff19166001179055919050565b6000610af061238e565b905090565b6033546001600160a01b03163314610b675760405162461bcd60e51b815260206004820152602f60248201527f56546f6b656e3a3a7377656570546f6b656e3a206f6e6c792061646d696e206360448201526e616e20737765657020746f6b656e7360881b6064820152608401610965565b60c9546001600160a01b03610100909104811690821603610be55760405162461bcd60e51b815260206004820152603260248201527f56546f6b656e3a3a7377656570546f6b656e3a2063616e206e6f74207377656560448201527138103ab73232b9363cb4b733903a37b5b2b760711b6064820152608401610965565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5091906145ea565b9050610c78610c676033546001600160a01b031690565b6001600160a01b0384169083612403565b6040516001600160a01b038316907f35ce4c546a473796a8e70ec2d4af4f2031afe357afa7057b6ea7fa340730e1b290600090a25050565b60c95460ff16610cd25760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff1916905560408051808201909152601981527f73657452657365727665466163746f722875696e7432353629000000000000006020820152610d199061246b565b610d2161182b565b5061099381612509565b60c95460009060ff16610d505760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610d6383612018565b610d6b61182b565b50610d77338484612592565b50600060c9805460ff1916600117905592915050565b60c95460009060ff16610db25760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610dc833858585612723565b50600160c9805460ff191660011790559392505050565b610e006040518060600160405280602481526020016148036024913961246b565b60008111610e405760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908125b9c1d5d609a1b6044820152606401610965565b60dc5460408051918252602082018390527fc2ac513cdb57f91eb2bef4db918c285829524f549682b99717c6cb06cc011183910160405180910390a160dc55565b60c95460009060ff16610ea65760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055610eb861182b565b50610ec433848461215f565b506000905060c9805460ff1916600117905592915050565b6000610ee783612018565b33600081815260d8602090815260408083206001600160a01b0388168452909152902054610f158482614619565b6001600160a01b03838116600081815260d860209081526040808320948b16808452948252918290208590559051848152939450919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3506001949350505050565b6000806040518060200160405280610f9a611b85565b90526001600160a01b038416600090815260d76020526040902054909150610fc3908290612910565b9392505050565b6000610af0612928565b610fdc61203f565b610a238161295e565b60c95460ff166110075760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055801561107d5760cd5460405163eade3eed60e01b81523060048201526001600160a01b0384811660248301529091169063eade3eed90604401600060405180830381600087803b15801561106457600080fd5b505af1158015611078573d6000803e3d6000fd5b505050505b60cd546001600160a01b031633146110a857604051632c40292560e01b815260040160405180910390fd5b60006110b38361231e565b60d35490915060008315611133576110cb86856129b9565b90506110d78183614631565b91506001600160a01b038086169087167f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1836111138188614631565b604080519283526020830191909152810186905260600160405180910390a35b600061113f8285614631565b905080156112075760d65460006111568383614619565b90506111628386614631565b60d682905560408051858152600060208201529081018290529095506001600160a01b0389169030907f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060600160405180910390a360408051848152602081018490529081018290526001600160a01b038916907f90125ffdb441e57c4f6bf69789206424859f206bea5727f2d81ad2470826ef6a9060600160405180910390a250505b6001600160a01b03808716600081815260d9602052604080822091825560d25460019092019190915560d38690555190918916907f9fe0294717a8efbc6ace1c151b73a4c89982339b2228a27d1ca21394e348986f9061126a9089815260200190565b60405180910390a3505060c9805460ff191660011790555050505050565b61129061203f565b61129a6000612ac7565b565b60c95460009060ff166112c15760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff191690556112d361182b565b505060d35460c9805460ff1916600117905590565b6113266040518060400160405280601e81526020017f73657450726f746f636f6c5365697a6553686172652875696e7432353629000081525061246b565b60cd5460408051634ada90af60e01b815290516000926001600160a01b031691634ada90af9160048083019260209291908290030181865afa158015611370573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139491906145ea565b9050806113a9670de0b6b3a764000084614619565b11156113c85760405163034dd2c160e11b815260040160405180910390fd5b60da80549083905560408051828152602081018590527ff5815f353a60e815cce7553e4f60c533a59d26b1b5504ea4b6db8d60da3e4da291015b60405180910390a1505050565b60c95460ff166114315760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff1916905561144361182b565b5061144d81612ae0565b505060c9805460ff19166001179055565b60655433906001600160a01b031681146114cc5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610965565b610a2381612ac7565b60c95460009060ff166114fa5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff1916905561150c61182b565b5061151933600084612b6d565b50600060c9805460ff19166001179055919050565b600054610100900460ff161580801561154e5750600054600160ff909116105b806115685750303b158015611568575060005460ff166001145b6115cb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610965565b6000805460ff1916600117905580156115ee576000805461ff0019166101001790555b6115f785612018565b61160a8c8c8c8c8c8c8c8c8c8c8c612e38565b8015611650576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050505050565b60cd546001600160a01b0316331461168957604051635c85a5e760e01b815260040160405180910390fd5b6116968585858585613079565b5050505050565b6116db6040518060400160405280601d81526020017f736574496e746572657374526174654d6f64656c28616464726573732900000081525061246b565b6116e361182b565b50610a238161315a565b60cb80546108c29061458c565b60006117058261231e565b92915050565b60c95460009060ff166117305760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff1916905561174261182b565b50611519333384612592565b600061175983612018565b33600081815260d8602090815260408083206001600160a01b0388168452909152902054838110156117cd5760405162461bcd60e51b815260206004820152601e60248201527f64656372656173656420616c6c6f77616e63652062656c6f77207a65726f00006044820152606401610965565b6001600160a01b03828116600081815260d860209081526040808320948a1680845294825291829020948890039485905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259101610f71565b60d15460009043908181036118435760009250505090565b600061184d612928565b60d35460d45460d25460ce5460d6546040516301cee29d60e21b815260048101879052602481018690526044810185905260648101919091529495509293919290916000916001600160a01b03169063073b8a7490608401602060405180830381865afa1580156118c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e691906145ea565b905065048c2739500081111561193e5760405162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c792068696768000000006044820152606401610965565b600061194a8789614631565b9050600061196660405180602001604052808581525083613295565b905060006119748288612910565b905060006119828883614619565b905060006119a1604051806020016040528060d054815250848a6132c6565b905060006119b085898a6132c6565b60d18e905560d281905560d384905560d483905560dc5460dd54919250906119d8908f614631565b106119eb5760dd8d90556119eb82611ea3565b604080518c815260208101869052908101829052606081018490527f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc049060800160405180910390a160009d505050505050505050505050505090565b60c95460009060ff16611a6c5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611a8233808585612723565b50600160c9805460ff1916600117905592915050565b60ce546000906001600160a01b0316630cde8d1c611ab4612928565b60d35460d45460d05460d6546040516001600160e01b031960e088901b1681526004810195909552602485019390935260448401919091526064830152608482015260a4015b602060405180830381865afa158015611b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af091906145ea565b60c95460ff16611b5d5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611b73338484846132e7565b505060c9805460ff1916600117905550565b60c95460009060ff16611baa5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611bbc61182b565b50611bc561238e565b905060c9805460ff1916600117905590565b6001600160a01b038116600090815260d760205260408120548190819081908190611c018761231e565b611c0961238e565b93509350935093509193509193565b60c95460009060ff16611c3d5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611c4f61182b565b506115193383613615565b60c95460009060ff16611c7f5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff19169055611c9161182b565b5061151933836000612b6d565b60db546001600160a01b03163314611d0c5760405162461bcd60e51b815260206004820152602b60248201527f6f6e6c792073686f727466616c6c20636f6e74726163742063616e207570646160448201526a1d1948189859081919589d60aa1b6064820152608401610965565b60d654811115611d705760405162461bcd60e51b815260206004820152602960248201527f6d6f7265207468616e206261642064656274207265636f76657265642066726f604482015268369030bab1ba34b7b760b91b6064820152608401610965565b60d6546000611d7f8383614631565b60d681905560408051848152602081018390529192507f9e19ec7d2b8f8a94df8cc0072453ace318d221e3cbb2731d0eaa0baac856520f9101611402565b611dc561203f565b606580546001600160a01b0383166001600160a01b03199091168117909155611df66033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000611e3e338585856000613079565b5060009392505050565b60ce546000906001600160a01b031663073b8a74611e64612928565b60d35460d45460d6546040516001600160e01b031960e087901b1681526004810194909452602484019290925260448301526064820152608401611afa565b80600003611eae5750565b60004360d15414611ed257604051630dff50cb60e41b815260040160405180910390fd5b81611edb612928565b1015611efa57604051633345e99960e01b815260040160405180910390fd5b60d454821115611f1d576040516378d2980560e11b815260040160405180910390fd5b8160d454611f2b9190614631565b60d481905560cc54909150611f4e9061010090046001600160a01b03168361378b565b60cc5460cd5460c9546040516305bebb3b60e21b81526001600160a01b03610100948590048116946316faecec94611f96949083169391900490911690600090600401614648565b600060405180830381600087803b158015611fb057600080fd5b505af1158015611fc4573d6000803e3d6000fd5b505060cc5460408051868152602081018690526101009092046001600160a01b031693507f9cc63bb4ef37ad6a5f5f657dfaf94865531d4234acbc431cc8ac035468f6272092500160405180910390a25050565b6001600160a01b038116610a23576040516342bcdf7f60e11b815260040160405180910390fd5b6033546001600160a01b0316331461129a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610965565b6001600160a01b0381166120fd5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610965565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091015b60405180910390a15050565b60cd5460405163eade3eed60e01b81523060048201526001600160a01b038481166024830152600092169063eade3eed90604401600060405180830381600087803b1580156121ad57600080fd5b505af11580156121c1573d6000803e3d6000fd5b505050506121cc4390565b60d154146121ed5760405163c9021e2f60e01b815260040160405180910390fd5b60006121f88461231e565b905060008184101561220a578361220c565b815b9050600061221a87836129b9565b905060006122288285614631565b905060008260d35461223a9190614631565b6001600160a01b03898116600081815260d9602090815260409182902087815560d25460019091015560d3859055815188815290810187905290810184905292935091908b16907f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19060600160405180910390a35090979650505050505050565b6122c481612018565b60cc80546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907fafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b90600090a35050565b6001600160a01b038116600090815260d96020908152604080832081518083019092528054808352600190910154928201929092529082036123635750600092915050565b60d25481516000916123749161468c565b905081602001518161238691906146ab565b949350505050565b60d5546000908082036123a357505060cf5490565b60006123ad612928565b9050600060d45460d65460d354846123c59190614619565b6123cf9190614619565b6123d99190614631565b90506000836123f0670de0b6b3a76400008461468c565b6123fa91906146ab565b95945050505050565b6040516001600160a01b03831660248201526044810182905261246690849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526137a7565b505050565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab9061249e90339086906004016146cd565b602060405180830381865afa1580156124bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124df91906146f1565b90508061250557333083604051634a3fa29360e01b81526004016109659392919061470e565b5050565b4360d1541461252b57604051637dfca6b760e11b815260040160405180910390fd5b670de0b6b3a76400008111156125545760405163717220f360e11b815260040160405180910390fd5b60d080549082905560408051828152602081018490527faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f8214609101612153565b60cd5460405163c0891ba960e01b81526001600160a01b039091169063c0891ba9906125c69030908690869060040161473a565b600060405180830381600087803b1580156125e057600080fd5b505af11580156125f4573d6000803e3d6000fd5b505050506125ff4390565b60d15414612620576040516338d8859760e01b815260040160405180910390fd5b6000604051806020016040528061263561238e565b90529050600061264585846129b9565b90506000612653828461387c565b90508060d5546126639190614619565b60d5556001600160a01b038516600090815260d7602052604081205461268a908390614619565b6001600160a01b038716600081815260d760209081526040918290208490558151878152908101869052908101839052919250907fb4c03061fb5b7fed76389d5af8f2e0ddb09f8c70d1333abbb62582835e10accb9060600160405180910390a26040518281526001600160a01b038716906000906000805160206148278339815191529060200160405180910390a350505050505050565b60cd54604051636d0be88d60e01b81523060048201526001600160a01b03858116602483015284811660448301526064820184905290911690636d0be88d90608401600060405180830381600087803b15801561277f57600080fd5b505af1158015612793573d6000803e3d6000fd5b50505050816001600160a01b0316836001600160a01b0316036127c957604051638cd22d1960e01b815260040160405180910390fd5b6000836001600160a01b0316856001600160a01b0316036127ed5750600019612815565b506001600160a01b03808416600090815260d860209081526040808320938816835292905220545b60006128218383614631565b6001600160a01b038616600090815260d7602052604081205491925090612849908590614631565b6001600160a01b038616600090815260d7602052604081205491925090612871908690614619565b6001600160a01b03808916600090815260d76020526040808220869055918916815220819055905060001984146128cb576001600160a01b03808816600090815260d860209081526040808320938c168352929052208390555b856001600160a01b0316876001600160a01b0316600080516020614827833981519152876040516128fe91815260200190565b60405180910390a35050505050505050565b60008061291d8484613295565b90506123868161389a565b60c9546040516370a0823160e01b815230600482015260009161010090046001600160a01b0316906370a0823190602401611afa565b61296781612018565b60db80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef90600090a35050565b60c9546040516370a0823160e01b815230600482015260009161010090046001600160a01b031690829082906370a0823190602401602060405180830381865afa158015612a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2f91906145ea565b9050612a466001600160a01b0383168630876138b2565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015612a8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ab191906145ea565b9050612abd8282614631565b9695505050505050565b606580546001600160a01b0319169055610a23816138d9565b600080804360d15414612b09576040516338acf79960e01b815260048101829052602401610965565b612b1333856129b9565b90508060d454612b239190614619565b60d4819055604080518381526020810183905291935033917fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5910160405180910390a29392505050565b811580612b78575080155b612be15760405162461bcd60e51b815260206004820152603460248201527f6f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416044820152736d6f756e74496e206d757374206265207a65726f60601b6064820152608401610965565b4360d15414612c03576040516397b5cfcd60e01b815260040160405180910390fd5b60006040518060200160405280612c1861238e565b905290506000808415612c2d57849150612c6b565b612c37848461387c565b91506000612c45838561392b565b90508015801590612c565750848114155b15612c695782612c658161475e565b9350505b505b612c758383612910565b905080600003612cbe5760405162461bcd60e51b815260206004820152601460248201527372656465656d416d6f756e74206973207a65726f60601b6044820152606401610965565b60cd54604051634732387560e11b81526001600160a01b0390911690638e6470ea90612cf29030908a90879060040161473a565b600060405180830381600087803b158015612d0c57600080fd5b505af1158015612d20573d6000803e3d6000fd5b505050508060d454612d30612928565b612d3a9190614631565b1015612d59576040516391240a1b60e01b815260040160405180910390fd5b8160d554612d679190614631565b60d5556001600160a01b038616600090815260d76020526040812054612d8e908490614631565b6001600160a01b038816600090815260d7602052604090208190559050612db5878361378b565b60405183815230906001600160a01b038916906000805160206148278339815191529060200160405180910390a360408051838152602081018590529081018290526001600160a01b038816907fbd5034ffbd47e4e72a94baa2cdb74c6fad73cb3bcdc13036b72ec8306f5a76469060600160405180910390a250505050505050565b600054610100900460ff16612e5f5760405162461bcd60e51b815260040161096590614777565b612e6761394e565b612e708361397d565b60d154158015612e80575060d254155b612ed85760405162461bcd60e51b815260206004820152602360248201527f6d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6044820152626e636560e81b6064820152608401610965565b60cf88905587612f435760405162461bcd60e51b815260206004820152603060248201527f696e697469616c2065786368616e67652072617465206d75737420626520677260448201526f32b0ba32b9103a3430b7103d32b9379760811b6064820152608401610965565b612f4c8a6139a4565b4360d155670de0b6b3a764000060d255612f658961315a565b612f6e81612509565b8651612f819060ca9060208a01906140c5565b508551612f959060cb9060208901906140c5565b5060cc805460ff191660ff87161790558151612fb09061295e565b612fbd82602001516122bb565b66b1a2bc2ec5000060da5560c98054610100600160a81b0319166101006001600160a01b038e811682029290921792839055604080516318160ddd60e01b8152905191909304909116916318160ddd9160048083019260209291908290030181865afa158015613031573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061305591906145ea565b5060c9805460ff1916600117905561306c84612ac7565b5050505050505050505050565b60c95460ff1661309b5760405162461bcd60e51b8152600401610965906145c6565b60c9805460ff191690556130ad61182b565b506000826001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303816000875af11580156130f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061311491906145ea565b9050801561313857604051633eea49b760e11b815260048101829052602401610965565b6131458686868686613aaf565b505060c9805460ff1916600117905550505050565b60004360d1541461317e57604051630be2a5cb60e11b815260040160405180910390fd5b60ce60009054906101000a90046001600160a01b03169050816001600160a01b0316632191f92a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f891906146f1565b6132445760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401610965565b60ce80546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f92690600090a35050565b60408051602081019091526000815260405180602001604052806132bd856000015185613ee9565b90529392505050565b6000806132d38585613295565b90506123fa6132e18261389a565b84613ef5565b60cd5460405163037883e560e31b81523060048201526001600160a01b0386811660248301528581166044830152848116606483015290911690631bc41f2890608401600060405180830381600087803b15801561334457600080fd5b505af1158015613358573d6000803e3d6000fd5b50505050826001600160a01b0316826001600160a01b03160361338e57604051633a94626760e11b815260040160405180910390fd5b60cd5460408051634ada90af60e01b815290516000926001600160a01b031691634ada90af9160048083019260209291908290030181865afa1580156133d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133fc91906145ea565b9050600061341a83604051806020016040528060da5481525061392b565b905060006134368260405180602001604052808681525061387c565b905060006134448286614631565b90506000604051806020016040528061345b61238e565b90529050600061346b8285612910565b90508360d55461347b9190614631565b60d5556001600160a01b038816600090815260d760205260409020546134a2908890614631565b6001600160a01b03808a16600090815260d7602052604080822093909355908b16815220546134d2908490614619565b6001600160a01b03808b16600090815260d7602052604090209190915560cc5461350391610100909104168261378b565b60cc5460cd5460c9546040516305bebb3b60e21b81526001600160a01b03610100948590048116946316faecec9461354b949083169391900490911690600190600401614648565b600060405180830381600087803b15801561356557600080fd5b505af1158015613579573d6000803e3d6000fd5b50505050886001600160a01b0316886001600160a01b0316600080516020614827833981519152856040516135b091815260200190565b60405180910390a360cc546040516001600160a01b036101009092048216918a16907f3ac0548d62d3fa3c9a817cd33899b9acacd57e8958ebe51bc7d9a79f26a8a5db906136019085815260200190565b60405180910390a350505050505050505050565b60cd5460405163df71403b60e01b81526001600160a01b039091169063df71403b906136499030908690869060040161473a565b600060405180830381600087803b15801561366357600080fd5b505af1158015613677573d6000803e3d6000fd5b505050506136824390565b60d154146136a357604051630e8d8c6160e21b815260040160405180910390fd5b8060d4546136af612928565b6136b99190614631565b10156136d8576040516348c2588160e01b815260040160405180910390fd5b60006136e38361231e565b905060006136f18383614619565b905060008360d3546137039190614619565b6001600160a01b038616600090815260d96020526040902083815560d25460019091015560d38190559050613738858561378b565b60408051858152602081018490529081018290526001600160a01b038616907f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809060600160405180910390a25050505050565b60c95461010090046001600160a01b0316612466818484612403565b60006137fc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613f019092919063ffffffff16565b905080516000148061381d57508080602001905181019061381d91906146f1565b6124665760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610965565b6000610fc361389384670de0b6b3a7640000613ee9565b8351613f10565b805160009061170590670de0b6b3a7640000906146ab565b6138d3846323b872dd60e01b85858560405160240161242f9392919061473a565b50505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000670de0b6b3a7640000613944848460000151613ee9565b610fc391906146ab565b600054610100900460ff166139755760405162461bcd60e51b815260040161096590614777565b61129a613f1c565b600054610100900460ff16610a1a5760405162461bcd60e51b815260040161096590614777565b60cd5460408051623f1ee960e11b815290516001600160a01b0392831692841691627e3dd29160048083019260209291908290030181865afa1580156139ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a1291906146f1565b613a5e5760405162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c7365000000006044820152606401610965565b60cd80546001600160a01b0319166001600160a01b0384811691821790925560405190918316907f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d90600090a35050565b60cd5460405163e89d51ad60e01b81523060048201526001600160a01b03848116602483015286811660448301526064820186905283151560848301529091169063e89d51ad9060a401600060405180830381600087803b158015613b1357600080fd5b505af1158015613b27573d6000803e3d6000fd5b50505050613b324390565b60d15414613b53576040516380965b1b60e01b815260040160405180910390fd5b43826001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb691906145ea565b14613bd457604051631046f38d60e31b815260040160405180910390fd5b846001600160a01b0316846001600160a01b031603613c0657604051631bd1a62160e21b815260040160405180910390fd5b82600003613c275760405163d29da7ef60e01b815260040160405180910390fd5b6000198303613c4957604051635982c5bb60e11b815260040160405180910390fd5b6000613c5686868661215f565b60cd5460405163c488847b60e01b815291925060009182916001600160a01b03169063c488847b90613c909030908990889060040161473a565b6040805180830381865afa158015613cac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cd091906147c2565b9150915060008214613d405760405162461bcd60e51b815260206004820152603360248201527f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f604482015272105353d5539517d4d152569157d19052531151606a1b6064820152608401610965565b6040516370a0823160e01b81526001600160a01b0388811660048301528291908716906370a0823190602401602060405180830381865afa158015613d89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dad91906145ea565b1015613dfb5760405162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d55434800000000000000006044820152606401610965565b306001600160a01b03861603613e1c57613e17308989846132e7565b613e7f565b60405163b2a02ff160e01b81526001600160a01b0386169063b2a02ff190613e4c908b908b90869060040161473a565b600060405180830381600087803b158015613e6657600080fd5b505af1158015613e7a573d6000803e3d6000fd5b505050505b846001600160a01b0316876001600160a01b0316896001600160a01b03167f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb528685604051613ed7929190918252602082015260400190565b60405180910390a45050505050505050565b6000610fc3828461468c565b6000610fc38284614619565b60606123868484600085613f4c565b6000610fc382846146ab565b600054610100900460ff16613f435760405162461bcd60e51b815260040161096590614777565b61129a33612ac7565b606082471015613fad5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610965565b600080866001600160a01b03168587604051613fc991906147e6565b60006040518083038185875af1925050503d8060008114614006576040519150601f19603f3d011682016040523d82523d6000602084013e61400b565b606091505b509150915061401c87838387614027565b979650505050505050565b6060831561409657825160000361408f576001600160a01b0385163b61408f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610965565b5081612386565b61238683838151156140ab5781518083602001fd5b8060405162461bcd60e51b815260040161096591906141b6565b8280546140d19061458c565b90600052602060002090601f0160209004810192826140f35760008555614139565b82601f1061410c57805160ff1916838001178555614139565b82800160010185558215614139579182015b8281111561413957825182559160200191906001019061411e565b50614145929150614149565b5090565b5b80821115614145576000815560010161414a565b60005b83811015614179578181015183820152602001614161565b838111156138d35750506000910152565b600081518084526141a281602086016020860161415e565b601f01601f19169290920160200192915050565b602081526000610fc3602083018461418a565b6000602082840312156141db57600080fd5b5035919050565b6001600160a01b0381168114610a2357600080fd5b8035614202816141e2565b919050565b6000806040838503121561421a57600080fd5b8235614225816141e2565b946020939093013593505050565b60006020828403121561424557600080fd5b8135610fc3816141e2565b60008060006060848603121561426557600080fd5b8335614270816141e2565b92506020840135614280816141e2565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126142b857600080fd5b813567ffffffffffffffff808211156142d3576142d3614291565b604051601f8301601f19908116603f011681019082821181831017156142fb576142fb614291565b8160405283815286602085880101111561431457600080fd5b836020870160208301376000602085830101528094505050505092915050565b803560ff8116811461420257600080fd5b60006040828403121561435757600080fd5b6040516040810181811067ffffffffffffffff8211171561437a5761437a614291565b604052905080823561438b816141e2565b8152602083013561439b816141e2565b6020919091015292915050565b60008060008060008060008060008060006101808c8e0312156143ca57600080fd5b6143d38c6141f7565b9a506143e160208d016141f7565b99506143ef60408d016141f7565b985060608c0135975067ffffffffffffffff8060808e0135111561441257600080fd5b6144228e60808f01358f016142a7565b97508060a08e0135111561443557600080fd5b506144468d60a08e01358e016142a7565b955061445460c08d01614334565b945061446260e08d016141f7565b93506144716101008d016141f7565b92506144818d6101208e01614345565b91506101608c013590509295989b509295989b9093969950565b8015158114610a2357600080fd5b600080600080600060a086880312156144c157600080fd5b85356144cc816141e2565b945060208601356144dc816141e2565b93506040860135925060608601356144f3816141e2565b915060808601356145038161449b565b809150509295509295909350565b6000806040838503121561452457600080fd5b823561452f816141e2565b9150602083013561453f816141e2565b809150509250929050565b60008060006060848603121561455f57600080fd5b833561456a816141e2565b9250602084013591506040840135614581816141e2565b809150509250925092565b600181811c908216806145a057607f821691505b6020821081036145c057634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b6000602082840312156145fc57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561462c5761462c614603565b500190565b60008282101561464357614643614603565b500390565b6001600160a01b03848116825283166020820152606081016002831061467e57634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b60008160001904831182151516156146a6576146a6614603565b500290565b6000826146c857634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b03831681526040602082018190526000906123869083018461418a565b60006020828403121561470357600080fd5b8151610fc38161449b565b6001600160a01b038481168252831660208201526060604082018190526000906123fa9083018461418a565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001820161477057614770614603565b5060010190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600080604083850312156147d557600080fd5b505080516020909101519092909150565b600082516147f881846020870161415e565b919091019291505056fe7365745265647563655265736572766573426c6f636b44656c74612875696e7432353629ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220ce57b3aa2fd5fc240f24aa84c4d021e7ab68ec84ae7ae60fdb58968caec6e1cb64736f6c634300080d0033", + "devdoc": { + "author": "Venus", + "kind": "dev", + "methods": { + "acceptOwnership()": { + "details": "The new owner accepts the ownership transfer." + }, + "accrueInterest()": { + "custom:access": "Not restricted", + "custom:event": "Emits AccrueInterest event on success", + "details": "This calculates interest accrued from the last checkpointed block up to the current block and writes new checkpoint to storage and reduce spread reserves to protocol share reserve if currentBlock - reduceReservesBlockNumber >= blockDelta", + "returns": { + "_0": "Always NO_ERROR" + } + }, + "addReserves(uint256)": { + "custom:access": "Not restricted", + "custom:event": "Emits ReservesAdded event; may emit AccrueInterest", + "params": { + "addAmount": "The amount of underlying token to add as reserves" + } + }, + "allowance(address,address)": { + "params": { + "owner": "The address of the account which owns the tokens to be spent", + "spender": "The address of the account which may transfer tokens" + }, + "returns": { + "_0": "amount The number of tokens allowed to be spent (type(uint256).max means infinite)" + } + }, + "approve(address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "ZeroAddressNotAllowed is thrown when spender address is zero", + "custom:event": "Emits Approval event", + "details": "This will overwrite the approval amount for `spender` and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)", + "params": { + "amount": "The number of tokens that are approved (uint256.max means infinite)", + "spender": "The address of the account which may transfer tokens" + }, + "returns": { + "_0": "success Whether or not the approval succeeded" + } + }, + "badDebtRecovered(uint256)": { + "custom:access": "Only Shortfall contract", + "custom:event": "Emits BadDebtRecovered event", + "details": "Called only when bad debt is recovered from auction", + "params": { + "recoveredAmount_": "The amount of bad debt recovered" + } + }, + "balanceOf(address)": { + "params": { + "owner": "The address of the account to query" + }, + "returns": { + "_0": "amount The number of tokens owned by `owner`" + } + }, + "balanceOfUnderlying(address)": { + "details": "This also accrues interest in a transaction", + "params": { + "owner": "The address of the account to query" + }, + "returns": { + "_0": "amount The amount of underlying owned by `owner`" + } + }, + "borrow(uint256)": { + "custom:access": "Not restricted", + "custom:error": "BorrowCashNotAvailable is thrown when the protocol has insufficient cash", + "custom:event": "Emits Borrow event; may emit AccrueInterest", + "params": { + "borrowAmount": "The amount of the underlying asset to borrow" + }, + "returns": { + "_0": "error Always NO_ERROR for compatibility with Venus core tooling" + } + }, + "borrowBalanceCurrent(address)": { + "params": { + "account": "The address whose balance should be calculated after updating borrowIndex" + }, + "returns": { + "_0": "borrowBalance The calculated balance" + } + }, + "borrowBalanceStored(address)": { + "params": { + "account": "The address whose balance should be calculated" + }, + "returns": { + "_0": "borrowBalance The calculated balance" + } + }, + "borrowRatePerBlock()": { + "returns": { + "_0": "rate The borrow interest rate per block, scaled by 1e18" + } + }, + "constructor": { + "custom:oz-upgrades-unsafe-allow": "constructor" + }, + "decreaseAllowance(address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "ZeroAddressNotAllowed is thrown when spender address is zero", + "custom:event": "Emits Approval event", + "params": { + "spender": "The address of the account which may transfer tokens", + "subtractedValue": "The number of tokens to remove from total approval" + }, + "returns": { + "_0": "success Whether or not the approval succeeded" + } + }, + "exchangeRateCurrent()": { + "returns": { + "_0": "exchangeRate Calculated exchange rate scaled by 1e18" + } + }, + "exchangeRateStored()": { + "details": "This function does not accrue interest before calculating the exchange rate", + "returns": { + "_0": "exchangeRate Calculated exchange rate scaled by 1e18" + } + }, + "forceLiquidateBorrow(address,address,uint256,address,bool)": { + "custom:access": "Only Comptroller", + "custom:error": "ForceLiquidateBorrowUnauthorized is thrown when the request does not come from ComptrollerLiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vTokenLiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vTokenLiquidateLiquidatorIsBorrower is thrown when trying to liquidate selfLiquidateCloseAmountIsZero is thrown when repayment amount is zeroLiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX", + "custom:event": "Emits LiquidateBorrow event; may emit AccrueInterest", + "params": { + "borrower": "The borrower of this vToken to be liquidated", + "liquidator": "The address repaying the borrow and seizing collateral", + "repayAmount": "The amount of the underlying borrowed asset to repay", + "skipLiquidityCheck": "If set to true, allows to liquidate up to 100% of the borrow regardless of the account liquidity", + "vTokenCollateral": "The market in which to seize collateral from the borrower" + } + }, + "getAccountSnapshot(address)": { + "details": "This is used by comptroller to more efficiently perform liquidity checks.", + "params": { + "account": "Address of the account to snapshot" + }, + "returns": { + "borrowBalance": "Amount owed in terms of underlying", + "error": "Always NO_ERROR for compatibility with Venus core tooling", + "exchangeRate": "Stored exchange rate", + "vTokenBalance": "User's balance of vTokens" + } + }, + "getCash()": { + "returns": { + "_0": "cash The quantity of underlying asset owned by this contract" + } + }, + "healBorrow(address,address,uint256)": { + "custom:access": "Only Comptroller", + "custom:error": "HealBorrowUnauthorized is thrown when the request does not come from Comptroller", + "custom:event": "Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest", + "details": "This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume the Comptroller does all the necessary checks before calling this function.", + "params": { + "borrower": "account to heal", + "payer": "account who repays the debt", + "repayAmount": "amount to repay" + } + }, + "increaseAllowance(address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "ZeroAddressNotAllowed is thrown when spender address is zero", + "custom:event": "Emits Approval event", + "params": { + "addedValue": "The number of additional tokens spender can transfer", + "spender": "The address of the account which may transfer tokens" + }, + "returns": { + "_0": "success Whether or not the approval succeeded" + } + }, + "initialize(address,address,address,uint256,string,string,uint8,address,address,(address,address),uint256)": { + "custom:error": "ZeroAddressNotAllowed is thrown when admin address is zeroZeroAddressNotAllowed is thrown when shortfall contract address is zeroZeroAddressNotAllowed is thrown when protocol share reserve address is zero", + "params": { + "accessControlManager_": "AccessControlManager contract address", + "admin_": "Address of the administrator of this token", + "comptroller_": "The address of the Comptroller", + "decimals_": "ERC-20 decimal precision of this token", + "initialExchangeRateMantissa_": "The initial exchange rate, scaled by 1e18", + "interestRateModel_": "The address of the interest rate model", + "name_": "ERC-20 name of this token", + "reserveFactorMantissa_": "Percentage of borrow interest that goes to reserves (from 0 to 1e18)", + "riskManagement": "Addresses of risk & income related contracts", + "symbol_": "ERC-20 symbol of this token", + "underlying_": "The address of the underlying asset" + } + }, + "isVToken()": { + "returns": { + "_0": "Always true" + } + }, + "liquidateBorrow(address,uint256,address)": { + "custom:access": "Not restricted", + "custom:error": "LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vTokenLiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vTokenLiquidateLiquidatorIsBorrower is thrown when trying to liquidate selfLiquidateCloseAmountIsZero is thrown when repayment amount is zeroLiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX", + "custom:event": "Emits LiquidateBorrow event; may emit AccrueInterest", + "params": { + "borrower": "The borrower of this vToken to be liquidated", + "repayAmount": "The amount of the underlying borrowed asset to repay", + "vTokenCollateral": "The market in which to seize collateral from the borrower" + }, + "returns": { + "_0": "error Always NO_ERROR for compatibility with Venus core tooling" + } + }, + "mint(uint256)": { + "custom:access": "Not restricted", + "custom:event": "Emits Mint and Transfer events; may emit AccrueInterest", + "details": "Accrues interest whether or not the operation succeeds, unless reverted", + "params": { + "mintAmount": "The amount of the underlying asset to supply" + }, + "returns": { + "_0": "error Always NO_ERROR for compatibility with Venus core tooling" + } + }, + "mintBehalf(address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "ZeroAddressNotAllowed is thrown when minter address is zero", + "custom:event": "Emits Mint and Transfer events; may emit AccrueInterest", + "details": "Accrues interest whether or not the operation succeeds, unless reverted", + "params": { + "mintAmount": "The amount of the underlying asset to supply", + "minter": "User whom the supply will be attributed to" + }, + "returns": { + "_0": "error Always NO_ERROR for compatibility with Venus core tooling" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pendingOwner()": { + "details": "Returns the address of the pending owner." + }, + "redeem(uint256)": { + "custom:access": "Not restricted", + "custom:error": "RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash", + "custom:event": "Emits Redeem and Transfer events; may emit AccrueInterest", + "details": "Accrues interest whether or not the operation succeeds, unless reverted", + "params": { + "redeemTokens": "The number of vTokens to redeem into underlying" + }, + "returns": { + "_0": "error Always NO_ERROR for compatibility with Venus core tooling" + } + }, + "redeemUnderlying(uint256)": { + "details": "Accrues interest whether or not the operation succeeds, unless reverted", + "params": { + "redeemAmount": "The amount of underlying to receive from redeeming vTokens" + }, + "returns": { + "_0": "error Always NO_ERROR for compatibility with Venus core tooling" + } + }, + "reduceReserves(uint256)": { + "custom:access": "Not restricted", + "custom:error": "ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cashReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have", + "custom:event": "Emits ReservesReduced event; may emit AccrueInterest", + "details": "Gracefully return if reserves already reduced in accrueInterest", + "params": { + "reduceAmount": "Amount of reduction to reserves" + } + }, + "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." + }, + "repayBorrow(uint256)": { + "custom:access": "Not restricted", + "custom:event": "Emits RepayBorrow event; may emit AccrueInterest", + "params": { + "repayAmount": "The amount to repay, or type(uint256).max for the full outstanding amount" + }, + "returns": { + "_0": "error Always NO_ERROR for compatibility with Venus core tooling" + } + }, + "repayBorrowBehalf(address,uint256)": { + "custom:access": "Not restricted", + "custom:event": "Emits RepayBorrow event; may emit AccrueInterest", + "params": { + "borrower": "the account with the debt being payed off", + "repayAmount": "The amount to repay, or type(uint256).max for the full outstanding amount" + }, + "returns": { + "_0": "error Always NO_ERROR for compatibility with Venus core tooling" + } + }, + "seize(address,address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self", + "custom:event": "Emits Transfer, ReservesAdded events", + "details": "Will fail unless called by another vToken during the process of liquidation. It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.", + "params": { + "borrower": "The account having collateral seized", + "liquidator": "The account receiving seized collateral", + "seizeTokens": "The number of vTokens to seize" + } + }, + "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" + } + }, + "setInterestRateModel(address)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized error is thrown when the call is not authorized by AccessControlManager", + "custom:event": "Emits NewMarketInterestRateModel event; may emit AccrueInterest", + "details": "Admin function to accrue interest and update the interest rate model", + "params": { + "newInterestRateModel": "the new interest rate model to use" + } + }, + "setProtocolSeizeShare(uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized error is thrown when the call is not authorized by AccessControlManagerProtocolSeizeShareTooBig is thrown when the new seize share is too high", + "custom:event": "Emits NewProtocolSeizeShare event on success", + "details": "must be equal or less than liquidation incentive - 1", + "params": { + "newProtocolSeizeShareMantissa_": "new protocol share mantissa" + } + }, + "setProtocolShareReserve(address)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when protocol share reserve address is zero", + "params": { + "protocolShareReserve_": "The address of the protocol share reserve contract" + } + }, + "setReduceReservesBlockDelta(uint256)": { + "custom:access": "Only Governance", + "params": { + "_newReduceReservesBlockDelta": "block difference value" + } + }, + "setReserveFactor(uint256)": { + "custom:access": "Controlled by AccessControlManager", + "custom:error": "Unauthorized error is thrown when the call is not authorized by AccessControlManagerSetReserveFactorBoundsCheck is thrown when the new reserve factor is too high", + "custom:event": "Emits NewReserveFactor event; may emit AccrueInterest", + "details": "Admin function to accrue interest and set a new reserve factor", + "params": { + "newReserveFactorMantissa": "New reserve factor (from 0 to 1e18)" + } + }, + "setShortfallContract(address)": { + "custom:access": "Only Governance", + "custom:error": "ZeroAddressNotAllowed is thrown when shortfall contract address is zero", + "params": { + "shortfall_": "The address of the shortfall contract" + } + }, + "supplyRatePerBlock()": { + "returns": { + "_0": "rate The supply interest rate per block, scaled by 1e18" + } + }, + "sweepToken(address)": { + "custom:access": "Only Governance", + "params": { + "token": "The address of the ERC-20 token to sweep" + } + }, + "totalBorrowsCurrent()": { + "returns": { + "_0": "totalBorrows The total borrows with interest" + } + }, + "transfer(address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "TransferNotAllowed is thrown if trying to transfer to self", + "custom:event": "Emits Transfer event on success", + "params": { + "amount": "The number of tokens to transfer", + "dst": "The address of the destination account" + }, + "returns": { + "_0": "success True if the transfer succeeded, reverts otherwise" + } + }, + "transferFrom(address,address,uint256)": { + "custom:access": "Not restricted", + "custom:error": "TransferNotAllowed is thrown if trying to transfer to self", + "custom:event": "Emits Transfer event on success", + "params": { + "amount": "The number of tokens to transfer", + "dst": "The address of the destination account", + "src": "The address of the source account" + }, + "returns": { + "_0": "success True if the transfer succeeded, reverts otherwise" + } + }, + "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." + } + }, + "title": "VToken", + "version": 1 + }, + "userdoc": { + "errors": { + "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": { + "AccrueInterest(uint256,uint256,uint256,uint256)": { + "notice": "Event emitted when interest is accrued" + }, + "Approval(address,address,uint256)": { + "notice": "EIP20 Approval event" + }, + "BadDebtIncreased(address,uint256,uint256,uint256)": { + "notice": "Event emitted when bad debt is accumulated on a market" + }, + "BadDebtRecovered(uint256,uint256)": { + "notice": "Event emitted when bad debt is recovered via an auction" + }, + "Borrow(address,uint256,uint256,uint256)": { + "notice": "Event emitted when underlying is borrowed" + }, + "HealBorrow(address,address,uint256)": { + "notice": "Event emitted when healing the borrow" + }, + "LiquidateBorrow(address,address,uint256,address,uint256)": { + "notice": "Event emitted when a borrow is liquidated" + }, + "Mint(address,uint256,uint256,uint256)": { + "notice": "Event emitted when tokens are minted" + }, + "NewAccessControlManager(address,address)": { + "notice": "Emitted when access control manager contract address is changed" + }, + "NewComptroller(address,address)": { + "notice": "Event emitted when comptroller is changed" + }, + "NewMarketInterestRateModel(address,address)": { + "notice": "Event emitted when interestRateModel is changed" + }, + "NewProtocolSeizeShare(uint256,uint256)": { + "notice": "Event emitted when protocol seize share is changed" + }, + "NewProtocolShareReserve(address,address)": { + "notice": "Event emitted when protocol share reserve contract address is changed" + }, + "NewReduceReservesBlockDelta(uint256,uint256)": { + "notice": "Event emitted when reduce reserves block delta is changed" + }, + "NewReserveFactor(uint256,uint256)": { + "notice": "Event emitted when the reserve factor is changed" + }, + "NewShortfallContract(address,address)": { + "notice": "Event emitted when shortfall contract address is changed" + }, + "ProtocolSeize(address,address,uint256)": { + "notice": "Event emitted when liquidation reserves are reduced" + }, + "Redeem(address,uint256,uint256,uint256)": { + "notice": "Event emitted when tokens are redeemed" + }, + "RepayBorrow(address,address,uint256,uint256,uint256)": { + "notice": "Event emitted when a borrow is repaid" + }, + "ReservesAdded(address,uint256,uint256)": { + "notice": "Event emitted when the reserves are added" + }, + "SpreadReservesReduced(address,uint256,uint256)": { + "notice": "Event emitted when the spread reserves are reduced" + }, + "SweepToken(address)": { + "notice": "Event emitted when tokens are swept" + }, + "Transfer(address,address,uint256)": { + "notice": "EIP20 Transfer event" + } + }, + "kind": "user", + "methods": { + "accessControlManager()": { + "notice": "Returns the address of the access control manager contract" + }, + "accrualBlockNumber()": { + "notice": "Block number that interest was last accrued at" + }, + "accrueInterest()": { + "notice": "Applies accrued interest to total borrows and reserves" + }, + "addReserves(uint256)": { + "notice": "The sender adds to reserves." + }, + "allowance(address,address)": { + "notice": "Get the current allowance from `owner` for `spender`" + }, + "approve(address,uint256)": { + "notice": "Approve `spender` to transfer up to `amount` from `src`" + }, + "badDebt()": { + "notice": "Total bad debt of the market" + }, + "badDebtRecovered(uint256)": { + "notice": "Updates bad debt" + }, + "balanceOf(address)": { + "notice": "Get the token balance of the `owner`" + }, + "balanceOfUnderlying(address)": { + "notice": "Get the underlying balance of the `owner`" + }, + "borrow(uint256)": { + "notice": "Sender borrows assets from the protocol to their own address" + }, + "borrowBalanceCurrent(address)": { + "notice": "Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex" + }, + "borrowBalanceStored(address)": { + "notice": "Return the borrow balance of account based on stored data" + }, + "borrowIndex()": { + "notice": "Accumulator of the total earned interest rate since the opening of the market" + }, + "borrowRatePerBlock()": { + "notice": "Returns the current per-block borrow interest rate for this vToken" + }, + "comptroller()": { + "notice": "Contract which oversees inter-vToken operations" + }, + "decimals()": { + "notice": "EIP-20 token decimals for this token" + }, + "decreaseAllowance(address,uint256)": { + "notice": "Decreases approval for `spender`" + }, + "exchangeRateCurrent()": { + "notice": "Accrue interest then return the up-to-date exchange rate" + }, + "exchangeRateStored()": { + "notice": "Calculates the exchange rate from the underlying to the VToken" + }, + "forceLiquidateBorrow(address,address,uint256,address,bool)": { + "notice": "The extended version of liquidations, callable only by Comptroller. May skip the close factor check. The collateral seized is transferred to the liquidator." + }, + "getAccountSnapshot(address)": { + "notice": "Get a snapshot of the account's balances, and the cached exchange rate" + }, + "getCash()": { + "notice": "Get cash balance of this vToken in the underlying asset" + }, + "healBorrow(address,address,uint256)": { + "notice": "Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools may list risky assets or be configured improperly – we want to still handle such cases gracefully. We assume that Comptroller does the seizing, so this function is only available to Comptroller." + }, + "increaseAllowance(address,uint256)": { + "notice": "Increase approval for `spender`" + }, + "initialize(address,address,address,uint256,string,string,uint8,address,address,(address,address),uint256)": { + "notice": "Construct a new money market" + }, + "interestRateModel()": { + "notice": "Model which tells what the current interest rate should be" + }, + "isVToken()": { + "notice": "Indicator that this is a VToken contract (for inspection)" + }, + "liquidateBorrow(address,uint256,address)": { + "notice": "The sender liquidates the borrowers collateral. The collateral seized is transferred to the liquidator." + }, + "mint(uint256)": { + "notice": "Sender supplies assets into the market and receives vTokens in exchange" + }, + "mintBehalf(address,uint256)": { + "notice": "Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange" + }, + "name()": { + "notice": "EIP-20 token name for this token" + }, + "protocolSeizeShareMantissa()": { + "notice": "Share of seized collateral that is added to reserves" + }, + "protocolShareReserve()": { + "notice": "Protocol share Reserve contract address" + }, + "redeem(uint256)": { + "notice": "Sender redeems vTokens in exchange for the underlying asset" + }, + "redeemUnderlying(uint256)": { + "notice": "Sender redeems vTokens in exchange for a specified amount of underlying asset" + }, + "reduceReserves(uint256)": { + "notice": "Accrues interest and reduces reserves by transferring to the protocol reserve contract" + }, + "reduceReservesBlockDelta()": { + "notice": "delta block after which reserves will be reduced" + }, + "reduceReservesBlockNumber()": { + "notice": "last block number at which reserves were reduced" + }, + "repayBorrow(uint256)": { + "notice": "Sender repays their own borrow" + }, + "repayBorrowBehalf(address,uint256)": { + "notice": "Sender repays a borrow belonging to borrower" + }, + "reserveFactorMantissa()": { + "notice": "Fraction of interest currently set aside for reserves" + }, + "seize(address,address,uint256)": { + "notice": "Transfers collateral tokens (this market) to the liquidator." + }, + "setAccessControlManager(address)": { + "notice": "Sets the address of AccessControlManager" + }, + "setInterestRateModel(address)": { + "notice": "accrues interest and updates the interest rate model using _setInterestRateModelFresh" + }, + "setProtocolSeizeShare(uint256)": { + "notice": "sets protocol share accumulated from liquidations" + }, + "setProtocolShareReserve(address)": { + "notice": "Sets protocol share reserve contract address" + }, + "setReduceReservesBlockDelta(uint256)": { + "notice": "A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve" + }, + "setReserveFactor(uint256)": { + "notice": "accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh" + }, + "setShortfallContract(address)": { + "notice": "Sets shortfall contract address" + }, + "shortfall()": { + "notice": "Storage of Shortfall contract address" + }, + "supplyRatePerBlock()": { + "notice": "Returns the current per-block supply interest rate for this v" + }, + "sweepToken(address)": { + "notice": "A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)" + }, + "symbol()": { + "notice": "EIP-20 token symbol for this token" + }, + "totalBorrows()": { + "notice": "Total amount of outstanding borrows of the underlying in this market" + }, + "totalBorrowsCurrent()": { + "notice": "Returns the current total borrows plus accrued interest" + }, + "totalReserves()": { + "notice": "Total amount of reserves of the underlying held in this market" + }, + "totalSupply()": { + "notice": "Total number of tokens in circulation" + }, + "transfer(address,uint256)": { + "notice": "Transfer `amount` tokens from `msg.sender` to `dst`" + }, + "transferFrom(address,address,uint256)": { + "notice": "Transfer `amount` tokens from `src` to `dst`" + }, + "underlying()": { + "notice": "Underlying asset for this VToken" + } + }, + "notice": "Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview, each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of the pool. The main actions a user regularly interacts with in a market are: - mint/redeem of vTokens; - transfer of vTokens; - borrow/repay a loan on an underlying asset; - liquidate a borrow or liquidate/heal an account. A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`. The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken` as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also pay off interest accrued on the borrow. The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller` and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`. Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 290, + "contract": "contracts/VToken.sol:VToken", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 293, + "contract": "contracts/VToken.sol:VToken", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1397, + "contract": "contracts/VToken.sol:VToken", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 162, + "contract": "contracts/VToken.sol:VToken", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 282, + "contract": "contracts/VToken.sol:VToken", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 71, + "contract": "contracts/VToken.sol:VToken", + "label": "_pendingOwner", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 150, + "contract": "contracts/VToken.sol:VToken", + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 5019, + "contract": "contracts/VToken.sol:VToken", + "label": "_accessControlManager", + "offset": 0, + "slot": "151", + "type": "t_contract(IAccessControlManagerV8)5204" + }, + { + "astId": 5024, + "contract": "contracts/VToken.sol:VToken", + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 22177, + "contract": "contracts/VToken.sol:VToken", + "label": "_notEntered", + "offset": 0, + "slot": "201", + "type": "t_bool" + }, + { + "astId": 22180, + "contract": "contracts/VToken.sol:VToken", + "label": "underlying", + "offset": 1, + "slot": "201", + "type": "t_address" + }, + { + "astId": 22183, + "contract": "contracts/VToken.sol:VToken", + "label": "name", + "offset": 0, + "slot": "202", + "type": "t_string_storage" + }, + { + "astId": 22186, + "contract": "contracts/VToken.sol:VToken", + "label": "symbol", + "offset": 0, + "slot": "203", + "type": "t_string_storage" + }, + { + "astId": 22189, + "contract": "contracts/VToken.sol:VToken", + "label": "decimals", + "offset": 0, + "slot": "204", + "type": "t_uint8" + }, + { + "astId": 22192, + "contract": "contracts/VToken.sol:VToken", + "label": "protocolShareReserve", + "offset": 1, + "slot": "204", + "type": "t_address_payable" + }, + { + "astId": 22202, + "contract": "contracts/VToken.sol:VToken", + "label": "comptroller", + "offset": 0, + "slot": "205", + "type": "t_contract(ComptrollerInterface)11350" + }, + { + "astId": 22206, + "contract": "contracts/VToken.sol:VToken", + "label": "interestRateModel", + "offset": 0, + "slot": "206", + "type": "t_contract(InterestRateModel)12267" + }, + { + "astId": 22208, + "contract": "contracts/VToken.sol:VToken", + "label": "initialExchangeRateMantissa", + "offset": 0, + "slot": "207", + "type": "t_uint256" + }, + { + "astId": 22211, + "contract": "contracts/VToken.sol:VToken", + "label": "reserveFactorMantissa", + "offset": 0, + "slot": "208", + "type": "t_uint256" + }, + { + "astId": 22214, + "contract": "contracts/VToken.sol:VToken", + "label": "accrualBlockNumber", + "offset": 0, + "slot": "209", + "type": "t_uint256" + }, + { + "astId": 22217, + "contract": "contracts/VToken.sol:VToken", + "label": "borrowIndex", + "offset": 0, + "slot": "210", + "type": "t_uint256" + }, + { + "astId": 22220, + "contract": "contracts/VToken.sol:VToken", + "label": "totalBorrows", + "offset": 0, + "slot": "211", + "type": "t_uint256" + }, + { + "astId": 22223, + "contract": "contracts/VToken.sol:VToken", + "label": "totalReserves", + "offset": 0, + "slot": "212", + "type": "t_uint256" + }, + { + "astId": 22226, + "contract": "contracts/VToken.sol:VToken", + "label": "totalSupply", + "offset": 0, + "slot": "213", + "type": "t_uint256" + }, + { + "astId": 22229, + "contract": "contracts/VToken.sol:VToken", + "label": "badDebt", + "offset": 0, + "slot": "214", + "type": "t_uint256" + }, + { + "astId": 22233, + "contract": "contracts/VToken.sol:VToken", + "label": "accountTokens", + "offset": 0, + "slot": "215", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 22239, + "contract": "contracts/VToken.sol:VToken", + "label": "transferAllowances", + "offset": 0, + "slot": "216", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 22244, + "contract": "contracts/VToken.sol:VToken", + "label": "accountBorrows", + "offset": 0, + "slot": "217", + "type": "t_mapping(t_address,t_struct(BorrowSnapshot)22174_storage)" + }, + { + "astId": 22247, + "contract": "contracts/VToken.sol:VToken", + "label": "protocolSeizeShareMantissa", + "offset": 0, + "slot": "218", + "type": "t_uint256" + }, + { + "astId": 22250, + "contract": "contracts/VToken.sol:VToken", + "label": "shortfall", + "offset": 0, + "slot": "219", + "type": "t_address" + }, + { + "astId": 22253, + "contract": "contracts/VToken.sol:VToken", + "label": "reduceReservesBlockDelta", + "offset": 0, + "slot": "220", + "type": "t_uint256" + }, + { + "astId": 22256, + "contract": "contracts/VToken.sol:VToken", + "label": "reduceReservesBlockNumber", + "offset": 0, + "slot": "221", + "type": "t_uint256" + }, + { + "astId": 22261, + "contract": "contracts/VToken.sol:VToken", + "label": "__gap", + "offset": 0, + "slot": "222", + "type": "t_array(t_uint256)48_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_address_payable": { + "encoding": "inplace", + "label": "address payable", + "numberOfBytes": "20" + }, + "t_array(t_uint256)48_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "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(ComptrollerInterface)11350": { + "encoding": "inplace", + "label": "contract ComptrollerInterface", + "numberOfBytes": "20" + }, + "t_contract(IAccessControlManagerV8)5204": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV8", + "numberOfBytes": "20" + }, + "t_contract(InterestRateModel)12267": { + "encoding": "inplace", + "label": "contract InterestRateModel", + "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_struct(BorrowSnapshot)22174_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct VTokenStorage.BorrowSnapshot)", + "numberOfBytes": "32", + "value": "t_struct(BorrowSnapshot)22174_storage" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(BorrowSnapshot)22174_storage": { + "encoding": "inplace", + "label": "struct VTokenStorage.BorrowSnapshot", + "members": [ + { + "astId": 22171, + "contract": "contracts/VToken.sol:VToken", + "label": "principal", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 22173, + "contract": "contracts/VToken.sol:VToken", + "label": "interestIndex", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} diff --git a/deployments/sepolia/VToken_vCRV_Core.json b/deployments/sepolia/VToken_vCRV_Core.json new file mode 100644 index 000000000..f2edc50e5 --- /dev/null +++ b/deployments/sepolia/VToken_vCRV_Core.json @@ -0,0 +1,246 @@ +{ + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x121E3be152F283319310D807ed847E8b98319C1e", + "transactionIndex": 28, + "gasUsed": "675899", + "logsBloom": "0x00000000000400080040000000000000000000000004000000800000000000000000000000000040000000020000000000000000000200000000400800048000001000000000000000000000001000000001000000040000000008000000002000000000020000000090000000000800000000100000000000000000008000400000040000000000000400000100080000004000000080100000000000000000000000000000000100000000040400000000000000800000000000000000004000000004000000000002020010040000000000000000000000800000000060004800020020000000000000800000000400000800000000020000000000010000", + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142", + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "logs": [ + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 30, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + }, + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 31, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + }, + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 32, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + }, + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70" + ], + "data": "0x", + "logIndex": 33, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + }, + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000710f4044007a0e72e54626394462db57d2d8479f" + ], + "data": "0x", + "logIndex": 34, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + }, + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003782dace9d90000", + "logIndex": 35, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + }, + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 36, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + }, + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 37, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + }, + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 38, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + }, + { + "transactionIndex": 28, + "blockNumber": 4776637, + "transactionHash": "0x4eab778f294674a324be581228f46f5301cd86b9033b3a40bf8a9e8a7babf501", + "address": "0x121E3be152F283319310D807ed847E8b98319C1e", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 39, + "blockHash": "0x6255636aa55290bb2a8e679839730c8b3e4a80222223d851d653728c94a1f142" + } + ], + "blockNumber": 4776637, + "cumulativeGasUsed": "3065105", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c3190000000000000000000000002c78ef7eab67a6e0c9caa6f2821929351bddf3d30000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70000000000000000000000000710f4044007a0e72e54626394462db57d2d8479f0000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf800000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000001056656e7573204352562028436f726529000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009764352565f436f72650000000000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vCRV_Curve.json b/deployments/sepolia/VToken_vCRV_Curve.json new file mode 100644 index 000000000..45dd4473f --- /dev/null +++ b/deployments/sepolia/VToken_vCRV_Curve.json @@ -0,0 +1,246 @@ +{ + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "transactionIndex": 45, + "gasUsed": "675935", + "logsBloom": "0x00000000000400080000000000000000000000000004000000840000000000000000000000000040000000020000000000000000004200000000000800048000001000000000000000000000001000000001000000040000000000000000002000000000020000000090000000000840000000000001000000000000008000400000040000000000000000000100080000000000000080100000000000000000001000000000000100000000000400000800004000800000000000000000004000000004000000000002000010040000000000000000000000800000000060000800020020000000000000800000000400000800000000020000000000010100", + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282", + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "logs": [ + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 25, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + }, + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 26, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + }, + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 27, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + }, + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000d298182d3acb43e98e32757ff09c91f203e9e67e" + ], + "data": "0x", + "logIndex": 28, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + }, + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000af5feabe347be5df603ce63e45155bdb8049c78c" + ], + "data": "0x", + "logIndex": 29, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + }, + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003782dace9d90000", + "logIndex": 30, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + }, + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 31, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + }, + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 32, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + }, + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 33, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + }, + { + "transactionIndex": 45, + "blockNumber": 4776644, + "transactionHash": "0x75981890bd7279b46fbf300c5450012b64580b77c2c6edd4079344de52870ca9", + "address": "0x9Db62c5BBc6fb79416545FcCBDB2204099217b78", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 34, + "blockHash": "0xd7643e2c0981b707a1102f4b9bd3c29ec8240b8fef2bcaf2ba8a718fd8c60282" + } + ], + "blockNumber": 4776644, + "cumulativeGasUsed": "7842008", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c3190000000000000000000000002c78ef7eab67a6e0c9caa6f2821929351bddf3d3000000000000000000000000d298182d3acb43e98e32757ff09c91f203e9e67e000000000000000000000000af5feabe347be5df603ce63e45155bdb8049c78c0000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf800000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000001156656e7573204352562028437572766529000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a764352565f437572766500000000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vUSDC_Core.json b/deployments/sepolia/VToken_vUSDC_Core.json new file mode 100644 index 000000000..5fa426aa5 --- /dev/null +++ b/deployments/sepolia/VToken_vUSDC_Core.json @@ -0,0 +1,246 @@ +{ + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "transactionIndex": 34, + "gasUsed": "675887", + "logsBloom": "0x00000000000400080000000000000100000000000004000000800000000000000000000000000040000000020000000000000000000200000000000800048000001008000000000000000000001000000001000000040400000088000000002000000000020000000090000000000800000000000000000000000000008000400000040000000000000000000100080000000000000080100000000000000000000000000000000100000000040400000000000000800000000000000000004000000004000000000002000010040000000000000000000000800000000060004800022020000000000000800000000400000800000000020000200000010000", + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986", + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "logs": [ + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 51, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + }, + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 52, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + }, + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 53, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + }, + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70" + ], + "data": "0x", + "logIndex": 54, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + }, + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3" + ], + "data": "0x", + "logIndex": 55, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + }, + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", + "logIndex": 56, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + }, + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 57, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + }, + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 58, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + }, + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 59, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + }, + { + "transactionIndex": 34, + "blockNumber": 4776633, + "transactionHash": "0xb2ae9e58e7eab808df8c5b0b8c39e3bc0ce98bec240c88dfe150f52222fa4f13", + "address": "0xF87bceab8DD37489015B426bA931e08A4D787616", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 60, + "blockHash": "0x7ae86dd4a21bbc25d6d6cb49e8170e5922b43f7469f3fbf943b488b28468a986" + } + ], + "blockNumber": 4776633, + "cumulativeGasUsed": "8880407", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c319000000000000000000000000772d68929655ce7234c8c94256526dda66ef641e0000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001156656e757320555344432028436f726529000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a76555344435f436f726500000000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vUSDC_Stablecoins.json b/deployments/sepolia/VToken_vUSDC_Stablecoins.json new file mode 100644 index 000000000..121404682 --- /dev/null +++ b/deployments/sepolia/VToken_vUSDC_Stablecoins.json @@ -0,0 +1,246 @@ +{ + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "transactionIndex": 77, + "gasUsed": "676043", + "logsBloom": "0x00000000000400080000000000000000000000040004000000800000000000000000000000000040000000020000000000000000000200000000000800048000001008000000004000000000001000000001000000040100000000000000002000000000020000000090000000200800000000000100000000000000028000400000040000000000000000000100080000000000000080100000000000000000000000000000000100000000000400000000000000800000000000000000004000000004000000000002000010040000000000000000000000800000000060000800022020000000000000800000000400000800000000020000200000010000", + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c", + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "logs": [ + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 96, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + }, + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 97, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + }, + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 98, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + }, + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000018ef8d2bee415b731c25662568dc1035001ceb2c" + ], + "data": "0x", + "logIndex": 99, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + }, + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3" + ], + "data": "0x", + "logIndex": 100, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + }, + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", + "logIndex": 101, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + }, + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 102, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + }, + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 103, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + }, + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 104, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + }, + { + "transactionIndex": 77, + "blockNumber": 4776639, + "transactionHash": "0x01d9be57f2b71b733d0b6a52cf7dc6812aac2b0585fcd90723dbc0111974282f", + "address": "0xD5f83FCbb4a62779D0B37b9E603CD19Ad84884F0", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 105, + "blockHash": "0x24ab02baa4134a7ee976e82c7452d489fcf8e3c76369991c23a28d2d8735d36c" + } + ], + "blockNumber": 4776639, + "cumulativeGasUsed": "12742289", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c319000000000000000000000000772d68929655ce7234c8c94256526dda66ef641e00000000000000000000000018ef8d2bee415b731c25662568dc1035001ceb2c000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001856656e757320555344432028537461626c65636f696e73290000000000000000000000000000000000000000000000000000000000000000000000000000001176555344435f537461626c65636f696e73000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vUSDT_Core.json b/deployments/sepolia/VToken_vUSDT_Core.json new file mode 100644 index 000000000..e63ef3314 --- /dev/null +++ b/deployments/sepolia/VToken_vUSDT_Core.json @@ -0,0 +1,246 @@ +{ + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "transactionIndex": 8, + "gasUsed": "675887", + "logsBloom": "0x00000000000400080000000000000000000000000004000000800000000000000000000000000040000000020000000000000000000240000000000800048000001008000000000000000000001000000001000000040000000088000000002000000000020000000090000000000800000000000000000000000000008000400000040000000000000000000100080000000000000080100000000000000000000000000000000100000000040400000100000000800000000000000000004000000004000000000002000010040000000000000000000000800000000060004800022020000000000000800000000400000800000000020000200000010000", + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b", + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "logs": [ + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + }, + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 2, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + }, + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 3, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + }, + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70" + ], + "data": "0x", + "logIndex": 4, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + }, + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3" + ], + "data": "0x", + "logIndex": 5, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + }, + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", + "logIndex": 6, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + }, + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 7, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + }, + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 8, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + }, + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 9, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + }, + { + "transactionIndex": 8, + "blockNumber": 4776634, + "transactionHash": "0x60a814fedd4baf6417d31d408ff71c7d68b87c6d0d7d907d46267e0bcc5a79c1", + "address": "0x19252AFD0B2F539C400aEab7d460CBFbf74c17ff", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 10, + "blockHash": "0xa4da49ce961edd94217e8933644475875fa03b922c236deda564c3dde00b888b" + } + ], + "blockNumber": 4776634, + "cumulativeGasUsed": "1857524", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c3190000000000000000000000008d412fd0bc5d826615065b931171eed10f5af2660000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001156656e757320555344542028436f726529000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a76555344545f436f726500000000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vUSDT_Stablecoins.json b/deployments/sepolia/VToken_vUSDT_Stablecoins.json new file mode 100644 index 000000000..bb3e172ce --- /dev/null +++ b/deployments/sepolia/VToken_vUSDT_Stablecoins.json @@ -0,0 +1,246 @@ +{ + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "transactionIndex": 24, + "gasUsed": "676043", + "logsBloom": "0x00000000000400080000000000000000000000040004000000800000000000000000000000000040000000020000000000000000000200000000000800048000001008000000004000000000011000000001000000040000000000000000002000000000220000000090000000200800008000000000000000000000008000400000040000000000000000000100080000000000000080100000000000000000000000000000000100000000000400000000000000800000000000000000004000000004000000000002000010040000000000000000000000800000000060000800022020000000000000800000000400000800000000020000200000010000", + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092", + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "logs": [ + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 23, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + }, + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 24, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + }, + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 25, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + }, + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000018ef8d2bee415b731c25662568dc1035001ceb2c" + ], + "data": "0x", + "logIndex": 26, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + }, + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3" + ], + "data": "0x", + "logIndex": 27, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + }, + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", + "logIndex": 28, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + }, + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 29, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + }, + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 30, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + }, + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 31, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + }, + { + "transactionIndex": 24, + "blockNumber": 4776640, + "transactionHash": "0x86c21df282f680f3a195580ede198394c90b025d4f87f6f304bb2483a475deb1", + "address": "0x93dff2053D4B08823d8B39F1dCdf8497f15200f4", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 32, + "blockHash": "0xe13d849622694f52adec6de8433ec4e8e25ab2ef10fd100f6476c2b18d6a3092" + } + ], + "blockNumber": 4776640, + "cumulativeGasUsed": "3760101", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c3190000000000000000000000008d412fd0bc5d826615065b931171eed10f5af26600000000000000000000000018ef8d2bee415b731c25662568dc1035001ceb2c000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001856656e757320555344542028537461626c65636f696e73290000000000000000000000000000000000000000000000000000000000000000000000000000001176555344545f537461626c65636f696e73000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vWBTC_Core.json b/deployments/sepolia/VToken_vWBTC_Core.json new file mode 100644 index 000000000..414200e76 --- /dev/null +++ b/deployments/sepolia/VToken_vWBTC_Core.json @@ -0,0 +1,246 @@ +{ + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "transactionIndex": 52, + "gasUsed": "675899", + "logsBloom": "0x00000000000400080000000000000000000000000004000000800000000000000000000000000040000000020000000000800000000200000000000800048000001000000000000000000000001000000001000000040000000008020000002000000000020000000090000040000800000000000000000000000000008000400000040000008000000000000100080000000000000080100000000000001000000000000000000100000000040400000000000010800000000000000000004000000004000000000002000010040000000000000000000000800000000060004800020020000000000000800000000400000800000000020000000000010000", + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5", + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "logs": [ + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 47, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + }, + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 48, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + }, + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 49, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + }, + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70" + ], + "data": "0x", + "logIndex": 50, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + }, + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000001a9ca9032c7ee7335736fcaa5e8fb62b283538da" + ], + "data": "0x", + "logIndex": 51, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + }, + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c68af0bb140000", + "logIndex": 52, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + }, + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 53, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + }, + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 54, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + }, + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 55, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + }, + { + "transactionIndex": 52, + "blockNumber": 4776628, + "transactionHash": "0x8fee2190e55b63d098f9563dee7399c22b2fdf85ec1a33cbd14b1553aeebeeda", + "address": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 56, + "blockHash": "0x2959c27709bc59acdeb5e3432842dbbe75910c917d047db15801726722019da5" + } + ], + "blockNumber": 4776628, + "cumulativeGasUsed": "8335510", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c31900000000000000000000000092a2928f5634bea89a195e7becf0f0feedab885b0000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d700000000000000000000000001a9ca9032c7ee7335736fcaa5e8fb62b283538da0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf800000000000000000000000000000000000000000000000002c68af0bb140000000000000000000000000000000000000000000000000000000000000000001156656e757320574254432028436f726529000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a76574254435f436f726500000000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vWETH_Core.json b/deployments/sepolia/VToken_vWETH_Core.json new file mode 100644 index 000000000..db0b0000f --- /dev/null +++ b/deployments/sepolia/VToken_vWETH_Core.json @@ -0,0 +1,246 @@ +{ + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "transactionIndex": 55, + "gasUsed": "675935", + "logsBloom": "0x00040000000400080000000000000000000000000004000000800000000000000000000000000040000000020000000000000000000200000000000800048000801000000000000000000000001000000001000000040000000008000000002000000200020000000090000000000800000000000000000000000000008200400040040000000000000000000100080000000000000080100000000000000000000000000000000100000000040400000000000000800000000000000000004000000004000000000002000010040000000000000000000000800000000060004800020020000000000000804000000400000800000000020000000000010000", + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e", + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "logs": [ + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 65, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + }, + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 66, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + }, + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 67, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + }, + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70" + ], + "data": "0x", + "logIndex": 68, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + }, + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e948bbe16a846988a501a33fb6a82af4e2f231ae" + ], + "data": "0x", + "logIndex": 69, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + }, + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c68af0bb140000", + "logIndex": 70, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + }, + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 71, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + }, + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 72, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + }, + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 73, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + }, + { + "transactionIndex": 55, + "blockNumber": 4776631, + "transactionHash": "0xefff69a5ae2afb55400dca796420cca6625e491648ebba615f0bc8fb33f13882", + "address": "0xc2931B1fEa69b6D6dA65a50363A8D75d285e4da9", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 74, + "blockHash": "0x3d62bfcb155a616358149628479df6d7551edf021fa624261cb3ffd42f9d535e" + } + ], + "blockNumber": 4776631, + "cumulativeGasUsed": "9469080", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c319000000000000000000000000700868cabb60e90d77b6588ce072d9859ec8e2810000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70000000000000000000000000e948bbe16a846988a501a33fb6a82af4e2f231ae0000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf800000000000000000000000000000000000000000000000002c68af0bb140000000000000000000000000000000000000000000000000000000000000000001156656e757320574554482028436f726529000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a76574554485f436f726500000000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vcrvUSD_Core.json b/deployments/sepolia/VToken_vcrvUSD_Core.json new file mode 100644 index 000000000..1458e3566 --- /dev/null +++ b/deployments/sepolia/VToken_vcrvUSD_Core.json @@ -0,0 +1,246 @@ +{ + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "transactionIndex": 45, + "gasUsed": "675983", + "logsBloom": "0x00000000000400080000000000000000000000000004000020800000000000000000000000000040000000020000000000000000000200000000000800048000001008000000000000000000001000000001000000040000000008000000002000000000020000000090000000000800000000000000000000000000008000400000040000000000000000000100080000000000000080100000000000000000000000000000000180000000040400000000000000800000000000000000004000000004000000000002000010040000000000000000000000800000000060004800022020000000000000c00000000400000800000000020000200000010000", + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0", + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "logs": [ + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 48, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + }, + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 49, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + }, + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 50, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + }, + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70" + ], + "data": "0x", + "logIndex": 51, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + }, + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3" + ], + "data": "0x", + "logIndex": 52, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + }, + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", + "logIndex": 53, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + }, + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 54, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + }, + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 55, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + }, + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 56, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + }, + { + "transactionIndex": 45, + "blockNumber": 4776635, + "transactionHash": "0xc6f37a28e1104d8674a8a60c2224c07abc6edc3b9489a0c7fad1f3078c8c3c99", + "address": "0xA09cFAd2e138fe6d8FF62df803892cbCb79ED082", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 57, + "blockHash": "0x53c34428415d876564b95231d027fd240e70effdcd47ba6e19ef97c4e9c51af0" + } + ], + "blockNumber": 4776635, + "cumulativeGasUsed": "6215117", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c31900000000000000000000000036421d873abca3e2be6bb3c819c0cf26374f63b60000000000000000000000007aa39ab4bca897f403425c9c6fdbd0f882be0d70000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea30000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001356656e7573206372765553442028436f72652900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c766372765553445f436f72650000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vcrvUSD_Curve.json b/deployments/sepolia/VToken_vcrvUSD_Curve.json new file mode 100644 index 000000000..5e488e7bd --- /dev/null +++ b/deployments/sepolia/VToken_vcrvUSD_Curve.json @@ -0,0 +1,246 @@ +{ + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0xc7be132027e191636172798B933202E0f9CAD548", + "transactionIndex": 19, + "gasUsed": "676007", + "logsBloom": "0x00000000000400080000000400000000000000000004000000840000000000000000000000000040000000020000000000000000004200000000000800048000001008000000000000000000001000000001000000040000000000000000002000000000020000000090000000000800000000000001000000000000008000400000040000000000000000000100080000000000000080100000000000000000000000000000000100000000000400000000000000800000000000000000004000000004000000000002000010040000000000000000000000800002000060000800022020000000000000800000040400000800000000020000200000010000", + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011", + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "logs": [ + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 28, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + }, + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 29, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + }, + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 30, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + }, + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000d298182d3acb43e98e32757ff09c91f203e9e67e" + ], + "data": "0x", + "logIndex": 31, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + }, + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3" + ], + "data": "0x", + "logIndex": 32, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + }, + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", + "logIndex": 33, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + }, + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 34, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + }, + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 35, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + }, + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 36, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + }, + { + "transactionIndex": 19, + "blockNumber": 4776642, + "transactionHash": "0x4df479297dc41c0fdf3a4e86c943d7379aa7d50401a1cb93bdae96057b06932c", + "address": "0xc7be132027e191636172798B933202E0f9CAD548", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 37, + "blockHash": "0xa2ae384d09efd868ebb183953d4bf54d9cad4983bfb94a5afe416ddb017ef011" + } + ], + "blockNumber": 4776642, + "cumulativeGasUsed": "3926733", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c31900000000000000000000000036421d873abca3e2be6bb3c819c0cf26374f63b6000000000000000000000000d298182d3acb43e98e32757ff09c91f203e9e67e000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea30000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001456656e7573206372765553442028437572766529000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d766372765553445f437572766500000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/VToken_vcrvUSD_Stablecoins.json b/deployments/sepolia/VToken_vcrvUSD_Stablecoins.json new file mode 100644 index 000000000..1a92929fa --- /dev/null +++ b/deployments/sepolia/VToken_vcrvUSD_Stablecoins.json @@ -0,0 +1,246 @@ +{ + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "beacon", + "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" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "transactionIndex": 29, + "gasUsed": "676139", + "logsBloom": "0x00000000000400080000000000000000000000440004000000800000000000000000000000000040000000020000000000000000000200000000000800048000001008000000004000000000001000000001000000040000000000000000002000000000020000000090000000200800000000000000000000000000008000400000040000000000000000000100080000000000000080100000000000000000000000000000000100000000000400000000000000800000000000000000004000000004000000040002000010040000000000000000000000800000000060000800022020000000000000800000000400000800000000020000200000010000", + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6", + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "logs": [ + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000000463a7e5221eae1990ceddb51a5821a68cda6008" + ], + "data": "0x", + "logIndex": 43, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + }, + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c" + ], + "data": "0x", + "logIndex": 44, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + }, + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc96", + "logIndex": 45, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + }, + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000018ef8d2bee415b731c25662568dc1035001ceb2c" + ], + "data": "0x", + "logIndex": 46, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + }, + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea3" + ], + "data": "0x", + "logIndex": 47, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + }, + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", + "logIndex": 48, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + }, + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 49, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + }, + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8" + ], + "data": "0x", + "logIndex": 50, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + }, + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000fea1c651a47fe29db9b1bf3cc1f224d8d9cff68c", + "0x00000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb" + ], + "data": "0x", + "logIndex": 51, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + }, + { + "transactionIndex": 29, + "blockNumber": 4776641, + "transactionHash": "0x9b97eff2d77e3693bc0a14a979bcef4dac549a95835f02e0168cdb58fa7c6201", + "address": "0x9C5e7a3B4db931F07A6534f9e44100DDDc78c408", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 52, + "blockHash": "0x2123076f784e54f09eca5c0523a0f2116fbb59859193071315a45c6054d39ac6" + } + ], + "blockNumber": 4776641, + "cumulativeGasUsed": "3708432", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0463a7E5221EAE1990cEddB51A5821a68cdA6008", + "0x8a42c31900000000000000000000000036421d873abca3e2be6bb3c819c0cf26374f63b600000000000000000000000018ef8d2bee415b731c25662568dc1035001ceb2c000000000000000000000000a03205bc635a772e533e7be36b5701e331a70ea30000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000800000000000000000000000094fa6078b6b8a26f0b6edffbe6501b22a10470fb000000000000000000000000bf705c00578d43b6147ab4eae04dbbed1cccdc9600000000000000000000000000000000000000000000000000000000000000010000000000000000000000004116ca92960df77756aaac3afd91361db657fbf8000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001a56656e7573206372765553442028537461626c65636f696e73290000000000000000000000000000000000000000000000000000000000000000000000000013766372765553445f537461626c65636f696e7300000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "cdedc94c3b6a3494ec3d604a8209c227", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beacon\",\"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\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\":\"BeaconProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x3cbef5ebc24b415252e2f8c0c9254555d30d9f085603b4b80d9b5ed20ab87e90\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x3b21ae06bf5957f73fa16754b0669c77b7abd8ba6c072d35c3281d446fdb86c2\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x85439e74ab467b6a23d45d32bdc9506cbc3760320289afd605f11638c4138e95\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xf09e68aa0dc6722a25bc46490e8d48ed864466d17313b8a0b254c36b54e49899\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405260405161091438038061091483398101604081905261002291610463565b61002e82826000610035565b505061058d565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610523565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610523565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108ed602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053e565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c95782516000036103c2576001600160a01b0385163b6103c25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d3565b6103d383836103db565b949350505050565b8151156103eb5781518083602001fd5b8060405162461bcd60e51b8152600401610169919061055a565b80516001600160a01b038116811461041c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561045257818101518382015260200161043a565b838111156100f95750506000910152565b6000806040838503121561047657600080fd5b61047f83610405565b60208401519092506001600160401b038082111561049c57600080fd5b818501915085601f8301126104b057600080fd5b8151818111156104c2576104c2610421565b604051601f8201601f19908116603f011681019083821181831017156104ea576104ea610421565b8160405282815288602084870101111561050357600080fd5b610514836020830160208801610437565b80955050505050509250929050565b60006020828403121561053557600080fd5b6102c882610405565b60008251610550818460208701610437565b9190910192915050565b6020815260008251806020840152610579816040850160208701610437565b601f01601f19169190910160400192915050565b6103518061059c6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f560279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb919061024c565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a5565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b60608315610210578251600003610209576001600160a01b0385163b6102095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161021a565b61021a8383610222565b949350505050565b8151156102325781518083602001fd5b8060405162461bcd60e51b815260040161020091906102c1565b60006020828403121561025e57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b83811015610290578181015183820152602001610278565b8381111561029f576000848401525b50505050565b600082516102b7818460208701610275565b9190910192915050565b60208152600082518060208401526102e0816040850160208701610275565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe297b55fecce116ce1eb9330ed9a20786628fb8686af0694c83f972893aa55a64736f6c634300080d0033", + "devdoc": { + "details": "This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't conflict with the storage layout of the implementation behind the proxy. _Available since v3.4._", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the proxy with `beacon`. If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. Requirements: - `beacon` must be a contract with the interface {IBeacon}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/sepolia/solcInputs/0e89febeebc7444140de8e67c9067d2c.json b/deployments/sepolia/solcInputs/0e89febeebc7444140de8e67c9067d2c.json new file mode 100644 index 000000000..557e5cb0c --- /dev/null +++ b/deployments/sepolia/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/sepolia/solcInputs/2bf9f23321dda7abe5f536a221df7bce.json b/deployments/sepolia/solcInputs/2bf9f23321dda7abe5f536a221df7bce.json new file mode 100644 index 000000000..e591f8f99 --- /dev/null +++ b/deployments/sepolia/solcInputs/2bf9f23321dda7abe5f536a221df7bce.json @@ -0,0 +1,285 @@ +{ + "language": "Solidity", + "sources": { + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "@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/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.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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 Venus Access Control Contract.\n * @dev The AccessControlledV8 contract is a wrapper around the OpenZeppelin AccessControl contract\n * It provides a standardized way to control access to methods within the Venus Smart Contract Ecosystem.\n * The contract allows the owner to set an AccessControlManager contract address.\n * It can restrict method calls based on the sender's role and the method's signature.\n */\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/AccessControlManager.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title Venus Access Control Contract\n * @author venus\n * @dev This contract is a wrapper of OpenZeppelin AccessControl\n *\t\textending it in a way to standartize access control\n *\t\twithin Venus Smart Contract Ecosystem\n */\ncontract AccessControlManager is AccessControl, IAccessControlManagerV8 {\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(address contractAddress, string calldata functionSig, address accountToPermit) 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 calldata 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 calldata 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 calldata functionSig\n ) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n return hasRole(role, account);\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\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/FeedRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface FeedRegistryInterface {\n function latestRoundDataByName(\n string memory base,\n string memory quote\n )\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n function decimalsByName(string memory base, string memory quote) external view returns (uint8);\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/PublicResolverInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\ninterface PublicResolverInterface {\n function addr(bytes32 node) external view returns (address payable);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/SIDRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\ninterface SIDRegistryInterface {\n function resolver(bytes32 node) external view returns (address);\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/oracles/BinanceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/SIDRegistryInterface.sol\";\nimport \"../interfaces/FeedRegistryInterface.sol\";\nimport \"../interfaces/PublicResolverInterface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport \"../interfaces/OracleInterface.sol\";\n\n/**\n * @title BinanceOracle\n * @author Venus\n * @notice This oracle fetches price of assets from Binance.\n */\ncontract BinanceOracle is AccessControlledV8, OracleInterface {\n address public sidRegistryAddress;\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Max stale period configuration for assets\n mapping(string => uint256) public maxStalePeriod;\n\n /// @notice Override symbols to be compatible with Binance feed registry\n mapping(string => string) public symbols;\n\n event MaxStalePeriodAdded(string indexed asset, uint256 maxStalePeriod);\n\n event SymbolOverridden(string indexed symbol, string overriddenSymbol);\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 /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Used to set the max stale period of an asset\n * @param symbol The symbol of the asset\n * @param _maxStalePeriod The max stake period\n */\n function setMaxStalePeriod(string memory symbol, uint256 _maxStalePeriod) external {\n _checkAccessAllowed(\"setMaxStalePeriod(string,uint256)\");\n if (_maxStalePeriod == 0) revert(\"stale period can't be zero\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n maxStalePeriod[symbol] = _maxStalePeriod;\n emit MaxStalePeriodAdded(symbol, _maxStalePeriod);\n }\n\n /**\n * @notice Used to override a symbol when fetching price\n * @param symbol The symbol to override\n * @param overrideSymbol The symbol after override\n */\n function setSymbolOverride(string calldata symbol, string calldata overrideSymbol) external {\n _checkAccessAllowed(\"setSymbolOverride(string,string)\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n symbols[symbol] = overrideSymbol;\n emit SymbolOverridden(symbol, overrideSymbol);\n }\n\n /**\n * @notice Sets the contracts required to fetch prices\n * @param _sidRegistryAddress Address of SID registry\n * @param _accessControlManager Address of the access control manager contract\n */\n function initialize(\n address _sidRegistryAddress,\n address _accessControlManager\n ) external initializer notNullAddress(_sidRegistryAddress) {\n sidRegistryAddress = _sidRegistryAddress;\n __AccessControlled_init(_accessControlManager);\n }\n\n /**\n * @notice Uses Space ID to fetch the feed registry address\n * @return feedRegistryAddress Address of binance oracle feed registry.\n */\n function getFeedRegistryAddress() public view returns (address) {\n bytes32 nodeHash = 0x94fe3821e0768eb35012484db4df61890f9a6ca5bfa984ef8ff717e73139faff;\n\n SIDRegistryInterface sidRegistry = SIDRegistryInterface(sidRegistryAddress);\n address publicResolverAddress = sidRegistry.resolver(nodeHash);\n PublicResolverInterface publicResolver = PublicResolverInterface(publicResolverAddress);\n\n return publicResolver.addr(nodeHash);\n }\n\n /**\n * @notice Gets the price of a asset from the binance oracle\n * @param asset Address of the asset\n * @return Price in USD\n */\n function getPrice(address asset) public view returns (uint256) {\n string memory symbol;\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n symbol = \"BNB\";\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n symbol = token.symbol();\n decimals = token.decimals();\n }\n\n string memory overrideSymbol = symbols[symbol];\n\n if (bytes(overrideSymbol).length != 0) {\n symbol = overrideSymbol;\n }\n\n return _getPrice(symbol, decimals);\n }\n\n function _getPrice(string memory symbol, uint256 decimals) internal view returns (uint256) {\n FeedRegistryInterface feedRegistry = FeedRegistryInterface(getFeedRegistryAddress());\n\n (, int256 answer, , uint256 updatedAt, ) = feedRegistry.latestRoundDataByName(symbol, \"USD\");\n if (answer <= 0) revert(\"invalid binance oracle price\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n if (deltaTime > maxStalePeriod[symbol]) revert(\"binance oracle price expired\");\n\n uint256 decimalDelta = feedRegistry.decimalsByName(symbol, \"USD\");\n return (uint256(answer) * (10 ** (18 - decimalDelta))) * (10 ** (18 - decimals));\n }\n}\n" + }, + "@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ChainlinkOracle\n * @author Venus\n * @notice This oracle fetches prices of assets from the Chainlink oracle.\n */\ncontract ChainlinkOracle is AccessControlledV8, OracleInterface {\n struct TokenConfig {\n /// @notice Underlying token address, which can't be a null address\n /// @notice Used to check if a token is supported\n /// @notice 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB for BNB\n address asset;\n /// @notice Chainlink feed address\n address feed;\n /// @notice Price expiration period of this asset\n uint256 maxStalePeriod;\n }\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Manually set an override price, useful under extenuating conditions such as price feed failure\n mapping(address => uint256) public prices;\n\n /// @notice Token config by assets\n mapping(address => TokenConfig) public tokenConfigs;\n\n /// @notice Emit when a price is manually set\n event PricePosted(address indexed asset, uint256 previousPriceMantissa, uint256 newPriceMantissa);\n\n /// @notice Emit when a token config is added\n event TokenConfigAdded(address indexed asset, address feed, uint256 maxStalePeriod);\n\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Manually set the price of a given asset\n * @param asset Asset address\n * @param price Asset price in 18 decimals\n * @custom:access Only Governance\n * @custom:event Emits PricePosted event on succesfully setup of asset price\n */\n function setDirectPrice(address asset, uint256 price) external notNullAddress(asset) {\n _checkAccessAllowed(\"setDirectPrice(address,uint256)\");\n\n uint256 previousPriceMantissa = prices[asset];\n prices[asset] = price;\n emit PricePosted(asset, previousPriceMantissa, price);\n }\n\n /**\n * @notice Add multiple token configs at the same time\n * @param tokenConfigs_ config array\n * @custom:access Only Governance\n * @custom:error Zero length error thrown, if length of the array in parameter 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 Initializes the owner of the contract\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n }\n\n /**\n * @notice Add single token config. asset & feed cannot be null addresses and maxStalePeriod must be positive\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error NotNullAddress error is thrown if token feed address is null\n * @custom:error Range error is thrown if maxStale period of token is not greater than zero\n * @custom:event Emits TokenConfigAdded event on succesfully setting of the token config\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.feed) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n if (tokenConfig.maxStalePeriod == 0) revert(\"stale period can't be zero\");\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(tokenConfig.asset, tokenConfig.feed, tokenConfig.maxStalePeriod);\n }\n\n /**\n * @notice Gets the price of a asset from the chainlink oracle\n * @param asset Address of the asset\n * @return Price in USD from Chainlink or a manually set price for the asset\n */\n function getPrice(address asset) public view returns (uint256) {\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n decimals = token.decimals();\n }\n\n return _getPriceInternal(asset, decimals);\n }\n\n /**\n * @notice Gets the Chainlink price for a given asset\n * @param asset address of the asset\n * @param decimals decimals of the asset\n * @return price Asset price in USD or a manually set price of the asset\n */\n function _getPriceInternal(address asset, uint256 decimals) internal view returns (uint256 price) {\n uint256 tokenPrice = prices[asset];\n if (tokenPrice != 0) {\n price = tokenPrice;\n } else {\n price = _getChainlinkPrice(asset);\n }\n\n uint256 decimalDelta = 18 - decimals;\n return price * (10 ** decimalDelta);\n }\n\n /**\n * @notice Get the Chainlink price for an asset, revert if token config doesn't exist\n * @dev The precision of the price feed is used to ensure the returned price has 18 decimals of precision\n * @param asset Address of the asset\n * @return price Price in USD, with 18 decimals of precision\n * @custom:error NotNullAddress error is thrown if the asset address is null\n * @custom:error Price error is thrown if the Chainlink price of asset is not greater than zero\n * @custom:error Timing error is thrown if current timestamp is less than the last updatedAt timestamp\n * @custom:error Timing error is thrown if time difference between current time and last updated time\n * is greater than maxStalePeriod\n */\n function _getChainlinkPrice(\n address asset\n ) private view notNullAddress(tokenConfigs[asset].asset) returns (uint256) {\n TokenConfig memory tokenConfig = tokenConfigs[asset];\n AggregatorV3Interface feed = AggregatorV3Interface(tokenConfig.feed);\n\n // note: maxStalePeriod cannot be 0\n uint256 maxStalePeriod = tokenConfig.maxStalePeriod;\n\n // Chainlink USD-denominated feeds store answers at 8 decimals, mostly\n uint256 decimalDelta = 18 - feed.decimals();\n\n (, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData();\n if (answer <= 0) revert(\"chainlink price must be positive\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n\n if (deltaTime > maxStalePeriod) revert(\"chainlink price expired\");\n\n return uint256(answer) * (10 ** decimalDelta);\n }\n}\n" + }, + "contracts/BaseJumpRateModelV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { EXP_SCALE, MANTISSA_ONE } from \"./lib/constants.sol\";\n\n/**\n * @title Logic for Compound's JumpRateModel Contract V2.\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\n */\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\n /**\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\n */\n uint256 public immutable blocksPerYear;\n /**\n * @notice The address of the AccessControlManager contract\n */\n IAccessControlManagerV8 public accessControlManager;\n\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public baseRatePerBlock;\n\n /**\n * @notice The multiplier per block after hitting a specified utilization point\n */\n uint256 public jumpMultiplierPerBlock;\n\n /**\n * @notice The utilization point at which the jump multiplier is applied\n */\n uint256 public kink;\n\n event NewInterestParams(\n uint256 baseRatePerBlock,\n uint256 multiplierPerBlock,\n uint256 jumpMultiplierPerBlock,\n uint256 kink\n );\n\n /**\n * @notice Thrown when the action is prohibited by AccessControlManager\n */\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n /**\n * @notice Construct an interest rate model\n * @param blocksPerYear_ The approximate number of blocks per year that is assumed by the interest rate model.\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n * @param accessControlManager_ The address of the AccessControlManager contract\n */\n constructor(\n uint256 blocksPerYear_,\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_,\n IAccessControlManagerV8 accessControlManager_\n ) {\n require(address(accessControlManager_) != address(0), \"invalid ACM address\");\n require(blocksPerYear_ != 0, \"Invalid blocks per year\");\n accessControlManager = accessControlManager_;\n blocksPerYear = blocksPerYear_;\n\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\n }\n\n /**\n * @notice Update the parameters of the interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n * @custom:error Unauthorized if the sender is not allowed to call this function\n * @custom:access Controlled by AccessControlManager\n */\n function updateJumpRateModel(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_\n ) external virtual {\n string memory signature = \"updateJumpRateModel(uint256,uint256,uint256,uint256)\";\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) public view virtual override returns (uint256) {\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\n uint256 incomeToDistribute = borrows * rateToPool;\n uint256 supply = cash + borrows + badDebt - reserves;\n return incomeToDistribute / supply;\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @param badDebt The amount of badDebt in the market\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\n */\n function utilizationRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows and badDebt\n if ((borrows + badDebt) == 0) {\n return 0;\n }\n\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\n\n if (rate > EXP_SCALE) {\n rate = EXP_SCALE;\n }\n\n return rate;\n }\n\n /**\n * @notice Internal function to update the parameters of the interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n */\n function _updateJumpRateModel(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_\n ) internal {\n baseRatePerBlock = baseRatePerYear / blocksPerYear;\n multiplierPerBlock = multiplierPerYear / blocksPerYear;\n jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear;\n kink = kink_;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function _getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) internal view returns (uint256) {\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\n uint256 kink_ = kink;\n\n if (util <= kink_) {\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n }\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n uint256 excessUtil;\n unchecked {\n excessUtil = util - kink_;\n }\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\n }\n}\n" + }, + "contracts/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\n\n /// @notice Emitted when a collateral factor is changed by admin\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\n );\n\n /// @notice Emitted when liquidation incentive is changed by admin\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\n\n /// @notice Emitted when borrow cap for a vToken is changed\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\n\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\n\n /// @notice Emitted when supply cap for a vToken is changed\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\n\n /// @notice Emitted when a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\n\n /// @notice Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow.\n * @param vTokenAddress The address of the asset to be removed\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\n\n Market storage marketToExit = markets[address(vToken)];\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return NO_ERROR;\n }\n\n /* Set vToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete vToken from the account’s list of assets */\n // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\n\n /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param vToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param vToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param vToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param vToken The market to verify the repay against\n * @param borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if the market is deprecated or it is a forced liquidation */\n if (skipLiquidityCheck || isDeprecated(VToken(vTokenBorrowed))) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\n }\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param vToken The market to verify the transfer against\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\n _checkActionPauseState(vToken, Action.TRANSFER);\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = accountAssets[user];\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = accountAssets[borrower];\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\n // Set liquidation incentive to new incentive\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n // Emit event with old incentive, new incentive\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"setMarketBorrowCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \"invalid input\");\n\n _ensureMaxLoops(numMarkets);\n\n for (uint256 i; i < numMarkets; ++i) {\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\n }\n }\n\n /**\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall Hypothetical account shortfall below collateral requirements\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market.\n * @return markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\n }\n\n /**\n * @notice Check if a market is marked as listed (active)\n * @param vToken vToken Address for the market to check\n * @return listed True if listed otherwise false\n */\n function isMarketListed(VToken vToken) external view returns (bool) {\n return markets[address(vToken)].isListed;\n }\n\n /*** Assets You Are In ***/\n\n /**\n * @notice Returns the assets an account has entered\n * @param account The address of the account to pull assets for\n * @return A list with the assets the account has entered\n */\n function getAssetsIn(address account) external view returns (VToken[] memory) {\n VToken[] memory assetsIn = accountAssets[account];\n\n return assetsIn;\n }\n\n /**\n * @notice Returns whether the given account is entered in a given market\n * @param account The address of the account to check\n * @param vToken The vToken to check\n * @return True if the account is in the market specified, otherwise false.\n */\n function checkMembership(address account, VToken vToken) external view returns (bool) {\n return markets[address(vToken)].accountMembership[account];\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = accountAssets[account];\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\n }\n\n /**\n * @notice Check if a vToken market has been deprecated\n * @dev All borrows in a deprecated vToken market can be immediately liquidated\n * @param vToken The market to check if deprecated\n * @return deprecated True if the given vToken market has been deprecated\n */\n function isDeprecated(VToken vToken) public view returns (bool) {\n return\n markets[address(vToken)].collateralFactorMantissa == 0 &&\n actionPaused(address(vToken), Action.BORROW) &&\n vToken.reserveFactorMantissa() == MANTISSA_ONE;\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param vToken The market to enter\n * @param borrower The address of the account to modify\n */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\n\n // survived the gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n accountAssets[borrower].push(vToken);\n\n emit MarketEntered(vToken, borrower);\n }\n\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\n }\n\n /**\n * @dev Pause/unpause an action on a market\n * @param market Market to pause/unpause the action on\n * @param action Action id to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n */\n function _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = accountAssets[account];\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\n\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // Multiplier representing the most one can borrow against their collateral in this market.\n // For instance, 0.9 to allow borrowing 90% of collateral value.\n // Must be between 0 and 1, and stored as a mantissa.\n uint256 collateralFactorMantissa;\n // Multiplier representing the collateralization after which the borrow is eligible\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\n // value. Must be between 0 and collateral factor, stored as a mantissa.\n uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\n enum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n }\n\n /**\n * @notice Oracle which gives the price of any given asset\n */\n ResilientOracleInterface public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\n uint256 public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives\n */\n uint256 public liquidationIncentiveMantissa;\n\n /**\n * @notice Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\n\n /**\n * @notice Official mapping of vTokens -> Market metadata\n * @dev Used e.g. to determine if a market is supported\n */\n mapping(address => Market) public markets;\n\n /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\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" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Compound\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract ExponentialNoError {\n struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return truncate(product);\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return add_(truncate(product), addend);\n }\n\n /**\n * @dev Checks if first Exp is less than second Exp.\n */\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa < right.mantissa;\n }\n\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, errorMessage);\n return uint32(n);\n }\n\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\n }\n\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), b.mantissa);\n }\n\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/IPancakeswapV2Router.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPancakeswapV2Router {\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n}\n" + }, + "contracts/JumpRateModelV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { BaseJumpRateModelV2 } from \"./BaseJumpRateModelV2.sol\";\n\n/**\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\n * @author Arr00\n * @notice Supports only for V2 vTokens\n */\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\n constructor(\n uint256 blocksPerYear_,\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_,\n IAccessControlManagerV8 accessControlManager_\n )\n BaseJumpRateModelV2(\n blocksPerYear_,\n baseRatePerYear,\n multiplierPerYear,\n jumpMultiplierPerYear,\n kink_,\n accessControlManager_\n )\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n /**\n * @notice Calculates the current borrow rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view override returns (uint256) {\n return _getBorrowRate(cash, borrows, reserves, badDebt);\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlock;\n uint256 borrowRatePerBlock;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = comptroller.getAllMarkets();\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\n\n return\n VTokenBalances({\n vToken: address(vToken),\n balanceOf: balanceOf,\n borrowBalanceCurrent: borrowBalanceCurrent,\n balanceOfUnderlying: balanceOfUnderlying,\n tokenBalance: tokenBalance,\n tokenAllowance: tokenAllowance\n });\n }\n\n /**\n * @notice Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlock: vToken.supplyRatePerBlock(),\n borrowRatePerBlock: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(address(vToken.comptroller()));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n return\n VTokenUnderlyingPrice({\n vToken: address(vToken),\n underlyingPrice: priceOracle.getUnderlyingPrice(address(vToken))\n });\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n (borrowState.index, borrowState.block, borrowState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenBorrowState(address(markets[i]));\n RewardTokenState memory supplyState;\n (supplyState.index, supplyState.block, supplyState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenSupplyState(address(markets[i]));\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, borrowAmount) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: borrowState.index }), ratio);\n borrowState.index = safe224(index.mantissa, \"new index overflows\");\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(supplyState.block));\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, supplyTokens) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: supplyState.index }), ratio);\n supplyState.index = safe224(index.mantissa, \"new index overflows\");\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/ApproveOrRevert.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nlibrary ApproveOrRevert {\n /// @notice Thrown if a contract is unable to approve a transfer\n error ApproveFailed();\n\n /// @notice Approves a transfer, ensuring that it is successful. This function supports non-compliant\n /// tokens like the ones that don't return a boolean value on success. Thus, such approve call supports\n /// three different kinds of tokens:\n /// * Compliant tokens that revert on failure\n /// * Compliant tokens that return false on failure\n /// * Non-compliant tokens that don't return a value\n /// @param token The contract address of the token which will be transferred\n /// @param spender The spender contract address\n /// @param amount The value of the transfer\n function approveOrRevert(IERC20Upgradeable token, address spender, uint256 amount) internal {\n bytes memory callData = abi.encodeCall(token.approve, (spender, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory result) = address(token).call(callData);\n\n if (!success || (result.length != 0 && !abi.decode(result, (bool)))) {\n revert ApproveFailed();\n }\n }\n}\n" + }, + "contracts/lib/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" + }, + "contracts/lib/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/lib/TokenDebtTracker.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n/**\n * @title TokenDebtTracker\n * @author Venus\n * @notice TokenDebtTracker is an abstract contract that handles transfers _out_ of the inheriting contract.\n * If there is an error transferring out (due to any reason, e.g. the token contract restricted the user from\n * receiving incoming transfers), the amount is recorded as a debt that can be claimed later.\n * @dev Note that the inheriting contract keeps some amount of users' tokens on its balance, so be careful when\n * using balanceOf(address(this))!\n */\nabstract contract TokenDebtTracker is Initializable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => (address user => uint256 amount)).\n * Tracks failed transfers: when a token transfer fails, we record the\n * amount of the transfer, so that the user can redeem this debt later.\n */\n mapping(IERC20Upgradeable => mapping(address => uint256)) public tokenDebt;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => uint256 amount) shows how many\n * tokens the contract owes to all users. This is useful for accounting to\n * understand how much of balanceOf(address(this)) is already owed to users.\n */\n mapping(IERC20Upgradeable => uint256) public totalTokenDebt;\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[48] private __gap;\n\n /**\n * @notice Emitted when the contract's debt to the user is increased due to a failed transfer\n * @param token Token address\n * @param user User address\n * @param amount The amount of debt added\n */\n event TokenDebtAdded(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Emitted when a user claims tokens that the contract owes them\n * @param token Token address\n * @param user User address\n * @param amount The amount transferred\n */\n event TokenDebtClaimed(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Thrown if the user tries to claim more tokens than they are owed\n * @param token The token the user is trying to claim\n * @param owedAmount The amount of tokens the contract owes to the user\n * @param amount The amount of tokens the user is trying to claim\n */\n error InsufficientDebt(address token, address user, uint256 owedAmount, uint256 amount);\n\n /**\n * @notice Thrown if trying to transfer more tokens than the contract currently has\n * @param token The token the contract is trying to transfer\n * @param recipient The recipient of the transfer\n * @param amount The amount of tokens the contract is trying to transfer\n * @param availableBalance The amount of tokens the contract currently has\n */\n error InsufficientBalance(address token, address recipient, uint256 amount, uint256 availableBalance);\n\n /**\n * @notice Transfers the tokens we owe to msg.sender, if any\n * @param token The token to claim\n * @param amount_ The amount of tokens to claim (or max uint256 to claim all)\n * @custom:error InsufficientDebt The contract doesn't have enough debt to the user\n */\n function claimTokenDebt(IERC20Upgradeable token, uint256 amount_) external {\n uint256 owedAmount = tokenDebt[token][msg.sender];\n uint256 amount = (amount_ == type(uint256).max ? owedAmount : amount_);\n if (amount > owedAmount) {\n revert InsufficientDebt(address(token), msg.sender, owedAmount, amount);\n }\n unchecked {\n // Safe because we revert if amount > owedAmount above\n tokenDebt[token][msg.sender] = owedAmount - amount;\n }\n totalTokenDebt[token] -= amount;\n emit TokenDebtClaimed(address(token), msg.sender, amount);\n token.safeTransfer(msg.sender, amount);\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function __TokenDebtTracker_init() internal onlyInitializing {\n __TokenDebtTracker_init_unchained();\n }\n\n // solhint-disable-next-line func-name-mixedcase, no-empty-blocks\n function __TokenDebtTracker_init_unchained() internal onlyInitializing {}\n\n /**\n * @dev Transfers tokens to the recipient if the contract has enough balance, or\n * records the debt if the transfer fails due to reasons unrelated to the contract's\n * balance (e.g. if the token forbids transfers to the recipient).\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @custom:error InsufficientBalance The contract doesn't have enough balance to transfer\n */\n function _transferOutOrTrackDebt(IERC20Upgradeable token, address to, uint256 amount) internal {\n uint256 balance = token.balanceOf(address(this));\n if (balance < amount) {\n revert InsufficientBalance(address(token), address(this), amount, balance);\n }\n _transferOutOrTrackDebtSkippingBalanceCheck(token, to, amount);\n }\n\n /**\n * @dev Transfers tokens to the recipient, or records the debt if the transfer fails\n * due to any reason, including insufficient balance.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n */\n function _transferOutOrTrackDebtSkippingBalanceCheck(IERC20Upgradeable token, address to, uint256 amount) internal {\n // We can't use safeTransfer here because we can't try-catch internal calls\n bool success = _tryTransferOut(token, to, amount);\n if (!success) {\n tokenDebt[token][to] += amount;\n totalTokenDebt[token] += amount;\n emit TokenDebtAdded(address(token), to, amount);\n }\n }\n\n /**\n * @dev Either transfers tokens to the recepient or returns false. Supports tokens\n * thet revert or return false to indicate failure, and the non-compliant ones\n * that do not return any value.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @return true if the transfer succeeded, false otherwise\n */\n function _tryTransferOut(IERC20Upgradeable token, address to, uint256 amount) private returns (bool) {\n bytes memory callData = abi.encodeCall(token.transfer, (to, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = address(token).call(callData);\n return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n }\n}\n" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\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\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\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 /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.approve(vTokenAddress, 0);\n underlying.approve(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title PoolRegistryInterface\n * @author Venus\n * @notice Interface implemented by `PoolRegistry`.\n */\ninterface PoolRegistryInterface {\n /**\n * @notice Struct for a Venus interest rate pool.\n */\n struct VenusPool {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n }\n\n /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each block for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller private comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n function initializeMarket(address vToken) external onlyComptroller {\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlock(address[],uint32[],uint32[])\");\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumber();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\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 */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumber = getBlockNumber();\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumber;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n function getBlockNumber() public view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumber();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\n * @param vToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n uint256 supplyIndex = supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n uint256 borrowIndex = borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\n\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n supplyState.index = safe224(\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n supplyState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n supplyState.block = blockNumber;\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n borrowState.index = safe224(\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n borrowState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n borrowState.block = blockNumber;\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n}\n" + }, + "contracts/RiskFund/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IProtocolShareReserve\n * @author Venus\n * @notice Interface implemented by `ProtocolShareReserve`.\n */\ninterface IProtocolShareReserve {\n function updateAssetsState(address comptroller, address asset) external;\n}\n" + }, + "contracts/RiskFund/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 swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external returns (uint256);\n\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updateAssetsState(address comptroller, address asset) external;\n\n function convertibleBaseAsset() external view returns (address);\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n" + }, + "contracts/RiskFund/ProtocolShareReserve.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 { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\nimport { IProtocolShareReserve } from \"./IProtocolShareReserve.sol\";\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { ReserveHelpers } from \"./ReserveHelpers.sol\";\nimport { IRiskFund } from \"./IRiskFund.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\ncontract ProtocolShareReserve is ExponentialNoError, ReserveHelpers, IProtocolShareReserve {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n address public protocolIncome;\n address public riskFund;\n // Percentage of funds not sent to the RiskFund contract when the funds are released, following the project Tokenomics\n uint256 private constant PROTOCOL_SHARE_PERCENTAGE = 50;\n uint256 private constant BASE_UNIT = 100;\n\n /// @notice Emitted when funds are released\n event FundsReleased(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\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 /**\n * @notice Initializes the deployer to owner.\n * @param protocolIncome_ The address protocol income will be sent to\n * @param riskFund_ Risk fund address\n * @custom:error ZeroAddressNotAllowed is thrown when protocol income address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when risk fund address is zero\n */\n function initialize(address protocolIncome_, address riskFund_) external initializer {\n ensureNonzeroAddress(protocolIncome_);\n ensureNonzeroAddress(riskFund_);\n\n __Ownable2Step_init();\n\n protocolIncome = protocolIncome_;\n riskFund = riskFund_;\n }\n\n /**\n * @notice 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 address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Release funds\n * @param comptroller Pool's Comptroller\n * @param asset Asset to be released\n * @param amount Amount to release\n * @return Number of total released tokens\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function releaseFunds(address comptroller, address asset, uint256 amount) external nonReentrant returns (uint256) {\n ensureNonzeroAddress(asset);\n require(amount <= _poolsAssetsReserves[comptroller][asset], \"ProtocolShareReserve: Insufficient pool balance\");\n\n assetsReserves[asset] -= amount;\n _poolsAssetsReserves[comptroller][asset] -= amount;\n uint256 protocolIncomeAmount = mul_(\n Exp({ mantissa: amount }),\n div_(Exp({ mantissa: PROTOCOL_SHARE_PERCENTAGE * EXP_SCALE }), BASE_UNIT)\n ).mantissa;\n\n address riskFund_ = riskFund;\n\n emit FundsReleased(comptroller, asset, amount);\n\n IERC20Upgradeable(asset).safeTransfer(protocolIncome, protocolIncomeAmount);\n IERC20Upgradeable(asset).safeTransfer(riskFund_, amount - protocolIncomeAmount);\n\n // Update the pool asset's state in the risk fund for the above transfer.\n IRiskFund(riskFund_).updateAssetsState(comptroller, asset);\n\n return amount;\n }\n\n /**\n * @notice 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 */\n function updateAssetsState(\n address comptroller,\n address asset\n ) public override(IProtocolShareReserve, ReserveHelpers) {\n super.updateAssetsState(comptroller, asset);\n }\n}\n" + }, + "contracts/RiskFund/ReserveHelpers.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\n\ncontract ReserveHelpers is Ownable2StepUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 private constant NOT_ENTERED = 1;\n\n uint256 private constant ENTERED = 2;\n\n // Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools).\n mapping(address => uint256) public assetsReserves;\n\n // Store the asset's reserve per pool in the ProtocolShareReserve.\n // Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal _poolsAssetsReserves;\n\n // Address of pool registry contract\n address public poolRegistry;\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n uint256 internal status;\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 */\n uint256[46] private __gap;\n\n /// @notice Event emitted after the update of the assets reserves.\n /// @param comptroller Pool's Comptroller address\n /// @param asset Token address\n /// @param amount An amount by which the reserves have increased\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice event emitted on sweep token success\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(status != ENTERED, \"re-entered\");\n status = ENTERED;\n _;\n status = NOT_ENTERED;\n }\n\n /**\n * @notice A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input\n * @param _token The address of the BEP-20 token to sweep\n * @param _to Recipient of the output tokens.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n * @custom:access Only Owner\n */\n function sweepToken(address _token, address _to) external onlyOwner nonReentrant {\n ensureNonzeroAddress(_to);\n uint256 balanceDfference_;\n uint256 balance_ = IERC20Upgradeable(_token).balanceOf(address(this));\n\n require(balance_ > assetsReserves[_token], \"ReserveHelpers: Zero surplus tokens\");\n unchecked {\n balanceDfference_ = balance_ - assetsReserves[_token];\n }\n\n emit SweepToken(_token, _to, balanceDfference_);\n IERC20Upgradeable(_token).safeTransfer(_to, balanceDfference_);\n }\n\n /**\n * @notice 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 Asset's reserve in risk fund.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256) {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][asset];\n }\n\n /**\n * @notice 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 * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function updateAssetsState(address comptroller, address asset) public virtual {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n address poolRegistry_ = poolRegistry;\n require(poolRegistry_ != address(0), \"ReserveHelpers: Pool Registry address is not set\");\n require(\n PoolRegistryInterface(poolRegistry_).getVTokenForAsset(comptroller, asset) != address(0),\n \"ReserveHelpers: The pool doesn't support the asset\"\n );\n\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n assetsReserves[asset] += balanceDifference;\n _poolsAssetsReserves[comptroller][asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference);\n }\n }\n}\n" + }, + "contracts/RiskFund/RiskFund.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 { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { IRiskFund } from \"./IRiskFund.sol\";\nimport { ReserveHelpers } from \"./ReserveHelpers.sol\";\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { IPancakeswapV2Router } from \"../IPancakeswapV2Router.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { ApproveOrRevert } from \"../lib/ApproveOrRevert.sol\";\n\n/**\n * @title RiskFund\n * @author Venus\n * @notice Contract with basic features to track/hold different assets for different Comptrollers.\n * @dev This contract does not support BNB.\n */\ncontract RiskFund is AccessControlledV8, ExponentialNoError, ReserveHelpers, MaxLoopsLimitHelper, IRiskFund {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using ApproveOrRevert for IERC20Upgradeable;\n\n address public convertibleBaseAsset;\n address public shortfall;\n address public pancakeSwapRouter;\n uint256 public minAmountToConvert;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when shortfall contract address is updated\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\n\n /// @notice Emitted when convertible base asset is updated\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\n\n /// @notice Emitted when PancakeSwap router contract address is updated\n event PancakeSwapRouterUpdated(address indexed oldPancakeSwapRouter, address indexed newPancakeSwapRouter);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Emitted when pools assets are swapped\n event SwappedPoolsAssets(address[] markets, uint256[] amountsOutMin, uint256 totalAmount);\n\n /// @notice Emitted when reserves are transferred for auction\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\n\n /// @dev Note that the contract is upgradeable. Use initialize() or reinitializers\n /// to set the state variables.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner.\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @param minAmountToConvert_ Minimum amount assets must be worth to convert into base asset\n * @param convertibleBaseAsset_ Address of the base asset\n * @param accessControlManager_ Address of the access control contract\n * @param loopsLimit_ Limit for the loops in the contract to avoid DOS\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n */\n function initialize(\n address pancakeSwapRouter_,\n uint256 minAmountToConvert_,\n address convertibleBaseAsset_,\n address accessControlManager_,\n uint256 loopsLimit_\n ) external initializer {\n ensureNonzeroAddress(pancakeSwapRouter_);\n ensureNonzeroAddress(convertibleBaseAsset_);\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n require(loopsLimit_ > 0, \"Risk Fund: Loops limit can not be zero\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n pancakeSwapRouter = pancakeSwapRouter_;\n minAmountToConvert = minAmountToConvert_;\n convertibleBaseAsset = convertibleBaseAsset_;\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice 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 address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Shortfall contract address setter\n * @param shortfallContractAddress_ Address of the auction contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n */\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\n ensureNonzeroAddress(shortfallContractAddress_);\n\n address oldShortfallContractAddress = shortfall;\n shortfall = shortfallContractAddress_;\n emit ShortfallContractUpdated(oldShortfallContractAddress, shortfallContractAddress_);\n }\n\n /**\n * @notice PancakeSwap router address setter\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n */\n function setPancakeSwapRouter(address pancakeSwapRouter_) external onlyOwner {\n ensureNonzeroAddress(pancakeSwapRouter_);\n address oldPancakeSwapRouter = pancakeSwapRouter;\n pancakeSwapRouter = pancakeSwapRouter_;\n emit PancakeSwapRouterUpdated(oldPancakeSwapRouter, pancakeSwapRouter_);\n }\n\n /**\n * @notice Min amount to convert setter\n * @param minAmountToConvert_ Min amount to convert.\n */\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n uint256 oldMinAmountToConvert = minAmountToConvert;\n minAmountToConvert = minAmountToConvert_;\n emit MinAmountToConvertUpdated(oldMinAmountToConvert, minAmountToConvert_);\n }\n\n /**\n * @notice Sets a new convertible base asset\n * @param _convertibleBaseAsset Address for new convertible base asset.\n */\n function setConvertibleBaseAsset(address _convertibleBaseAsset) external {\n _checkAccessAllowed(\"setConvertibleBaseAsset(address)\");\n require(_convertibleBaseAsset != address(0), \"Risk Fund: new convertible base asset address invalid\");\n\n address oldConvertibleBaseAsset = convertibleBaseAsset;\n convertibleBaseAsset = _convertibleBaseAsset;\n\n emit ConvertibleBaseAssetUpdated(oldConvertibleBaseAsset, _convertibleBaseAsset);\n }\n\n /**\n * @notice Swap array of pool assets into base asset's tokens of at least a minimum amount\n * @param markets Array of vTokens whose assets to swap for base asset\n * @param amountsOutMin Minimum amount to receive for swap\n * @param paths A path consisting of PCS token pairs for each swap\n * @param deadline Deadline for the swap\n * @return Number of swapped tokens\n * @custom:error ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\n */\n function swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external override nonReentrant returns (uint256) {\n _checkAccessAllowed(\"swapPoolsAssets(address[],uint256[],address[][],uint256)\");\n require(deadline >= block.timestamp, \"Risk fund: deadline passed\");\n address poolRegistry_ = poolRegistry;\n ensureNonzeroAddress(poolRegistry_);\n require(markets.length == amountsOutMin.length, \"Risk fund: markets and amountsOutMin are unequal lengths\");\n require(markets.length == paths.length, \"Risk fund: markets and paths are unequal lengths\");\n\n uint256 totalAmount;\n uint256 marketsCount = markets.length;\n\n _ensureMaxLoops(marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n address comptroller = address(VToken(markets[i]).comptroller());\n\n PoolRegistry.VenusPool memory pool = PoolRegistry(poolRegistry_).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n require(Comptroller(comptroller).isMarketListed(VToken(markets[i])), \"market is not listed\");\n\n uint256 swappedTokens = _swapAsset(VToken(markets[i]), comptroller, amountsOutMin[i], paths[i]);\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] += swappedTokens;\n assetsReserves[convertibleBaseAsset] += swappedTokens;\n totalAmount = totalAmount + swappedTokens;\n }\n\n emit SwappedPoolsAssets(markets, amountsOutMin, totalAmount);\n\n return totalAmount;\n }\n\n /**\n * @notice Transfer tokens for auction.\n * @param comptroller Comptroller of the pool.\n * @param amount Amount to be transferred to auction contract.\n * @return Number reserved tokens.\n */\n function transferReserveForAuction(\n address comptroller,\n uint256 amount\n ) external override nonReentrant returns (uint256) {\n address shortfall_ = shortfall;\n require(msg.sender == shortfall_, \"Risk fund: Only callable by Shortfall contract\");\n require(\n amount <= _poolsAssetsReserves[comptroller][convertibleBaseAsset],\n \"Risk Fund: Insufficient pool reserve.\"\n );\n unchecked {\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] =\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] -\n amount;\n }\n unchecked {\n assetsReserves[convertibleBaseAsset] = assetsReserves[convertibleBaseAsset] - amount;\n }\n\n emit TransferredReserveForAuction(comptroller, amount);\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall_, amount);\n\n return amount;\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 */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\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 require(ComptrollerInterface(comptroller).isComptroller(), \"Risk Fund: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][convertibleBaseAsset];\n }\n\n /**\n * @notice Update the reserve of the asset for the specific pool after transferring to risk fund.\n * @param comptroller Comptroller address(pool).\n * @param asset Asset address.\n */\n function updateAssetsState(address comptroller, address asset) public override(IRiskFund, ReserveHelpers) {\n super.updateAssetsState(comptroller, asset);\n }\n\n /**\n * @dev Swap single asset to base asset.\n * @param vToken VToken\n * @param comptroller Comptroller address\n * @param amountOutMin Minimum amount to receive for swap\n * @param path A path for the swap consisting of PCS token pairs\n * @return Number of swapped tokens.\n */\n function _swapAsset(\n VToken vToken,\n address comptroller,\n uint256 amountOutMin,\n address[] calldata path\n ) internal returns (uint256) {\n require(amountOutMin != 0, \"RiskFund: amountOutMin must be greater than 0 to swap vToken\");\n uint256 totalAmount;\n\n address underlyingAsset = vToken.underlying();\n address convertibleBaseAsset_ = convertibleBaseAsset;\n uint256 balanceOfUnderlyingAsset = _poolsAssetsReserves[comptroller][underlyingAsset];\n\n if (balanceOfUnderlyingAsset == 0) {\n return 0;\n }\n\n ResilientOracleInterface oracle = ComptrollerViewInterface(comptroller).oracle();\n oracle.updateAssetPrice(convertibleBaseAsset_);\n Exp memory baseAssetPrice = Exp({ mantissa: oracle.getPrice(convertibleBaseAsset_) });\n uint256 amountOutMinInUsd = mul_ScalarTruncate(baseAssetPrice, amountOutMin);\n\n require(amountOutMinInUsd >= minAmountToConvert, \"RiskFund: minAmountToConvert violated\");\n\n assetsReserves[underlyingAsset] -= balanceOfUnderlyingAsset;\n _poolsAssetsReserves[comptroller][underlyingAsset] -= balanceOfUnderlyingAsset;\n\n if (underlyingAsset != convertibleBaseAsset_) {\n require(path[0] == underlyingAsset, \"RiskFund: swap path must start with the underlying asset\");\n require(\n path[path.length - 1] == convertibleBaseAsset_,\n \"RiskFund: finally path must be convertible base asset\"\n );\n address pancakeSwapRouter_ = pancakeSwapRouter;\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, 0);\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, balanceOfUnderlyingAsset);\n uint256[] memory amounts = IPancakeswapV2Router(pancakeSwapRouter_).swapExactTokensForTokens(\n balanceOfUnderlyingAsset,\n amountOutMin,\n path,\n address(this),\n block.timestamp\n );\n totalAmount = amounts[path.length - 1];\n } else {\n totalAmount = balanceOfUnderlyingAsset;\n }\n\n return totalAmount;\n }\n}\n" + }, + "contracts/Shortfall/Shortfall.sol": { + "content": "/// @notice SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { IRiskFund } from \"../RiskFund/IRiskFund.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { TokenDebtTracker } from \"../lib/TokenDebtTracker.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { EXP_SCALE } from \"../lib/constants.sol\";\n\n/**\n * @title Shortfall\n * @author Venus\n * @notice Shortfall is an auction contract designed to auction off the `convertibleBaseAsset` accumulated in `RiskFund`. The `convertibleBaseAsset`\n * is auctioned in exchange for users paying off the pool's bad debt. An auction can be started by anyone once a pool's bad debt has reached a minimum value.\n * This value is set and can be changed by the authorized accounts. If the pool’s bad debt exceeds the risk fund plus a 10% incentive, then the auction winner\n * is determined by who will pay off the largest percentage of the pool's bad debt. The auction winner then exchanges for the entire risk fund. Otherwise,\n * if the risk fund covers the pool's bad debt plus the 10% incentive, then the auction winner is determined by who will take the smallest percentage of the\n * risk fund in exchange for paying off all the pool's bad debt.\n */\ncontract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGuardUpgradeable, TokenDebtTracker {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Type of auction\n enum AuctionType {\n LARGE_POOL_DEBT,\n LARGE_RISK_FUND\n }\n\n /// @notice Status of auction\n enum AuctionStatus {\n NOT_STARTED,\n STARTED,\n ENDED\n }\n\n /// @notice Auction metadata\n struct Auction {\n uint256 startBlock;\n AuctionType auctionType;\n AuctionStatus status;\n VToken[] markets;\n uint256 seizedRiskFund;\n address highestBidder;\n uint256 highestBidBps;\n uint256 highestBidBlock;\n uint256 startBidBps;\n mapping(VToken => uint256) marketDebt;\n mapping(VToken => uint256) bidAmount;\n }\n\n /// @dev Max basis points i.e., 100%\n uint256 private constant MAX_BPS = 10000;\n\n uint256 private constant DEFAULT_NEXT_BIDDER_BLOCK_LIMIT = 100;\n\n uint256 private constant DEFAULT_WAIT_FOR_FIRST_BIDDER = 100;\n\n uint256 private constant DEFAULT_INCENTIVE_BPS = 1000; // 10%\n\n /// @notice Pool registry address\n address public poolRegistry;\n\n /// @notice Risk fund address\n IRiskFund public riskFund;\n\n /// @notice Minimum USD debt in pool for shortfall to trigger\n uint256 public minimumPoolBadDebt;\n\n /// @notice Incentive to auction participants, initial value set to 1000 or 10%\n uint256 public incentiveBps;\n\n /// @notice Time to wait for next bidder. Initially waits for 100 blocks\n uint256 public nextBidderBlockLimit;\n\n /// @notice Boolean of if auctions are paused\n bool public auctionsPaused;\n\n /// @notice Time to wait for first bidder. Initially waits for 100 blocks\n uint256 public waitForFirstBidder;\n\n /// @notice Auctions for each pool\n mapping(address => Auction) public auctions;\n\n /// @notice Emitted when a auction starts\n event AuctionStarted(\n address indexed comptroller,\n uint256 auctionStartBlock,\n AuctionType auctionType,\n VToken[] markets,\n uint256[] marketsDebt,\n uint256 seizedRiskFund,\n uint256 startBidBps\n );\n\n /// @notice Emitted when a bid is placed\n event BidPlaced(address indexed comptroller, uint256 auctionStartBlock, uint256 bidBps, address indexed bidder);\n\n /// @notice Emitted when a auction is completed\n event AuctionClosed(\n address indexed comptroller,\n uint256 auctionStartBlock,\n address indexed highestBidder,\n uint256 highestBidBps,\n uint256 seizedRiskFind,\n VToken[] markets,\n uint256[] marketDebt\n );\n\n /// @notice Emitted when a auction is restarted\n event AuctionRestarted(address indexed comptroller, uint256 auctionStartBlock);\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when minimum pool bad debt is updated\n event MinimumPoolBadDebtUpdated(uint256 oldMinimumPoolBadDebt, uint256 newMinimumPoolBadDebt);\n\n /// @notice Emitted when wait for first bidder block count is updated\n event WaitForFirstBidderUpdated(uint256 oldWaitForFirstBidder, uint256 newWaitForFirstBidder);\n\n /// @notice Emitted when next bidder block limit is updated\n event NextBidderBlockLimitUpdated(uint256 oldNextBidderBlockLimit, uint256 newNextBidderBlockLimit);\n\n /// @notice Emitted when incentiveBps is updated\n event IncentiveBpsUpdated(uint256 oldIncentiveBps, uint256 newIncentiveBps);\n\n /// @notice Emitted when auctions are paused\n event AuctionsPaused(address sender);\n\n /// @notice Emitted when auctions are unpaused\n event AuctionsResumed(address sender);\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 /**\n * @notice Initialize the shortfall contract\n * @param riskFund_ RiskFund contract address\n * @param minimumPoolBadDebt_ Minimum bad debt in base asset for a pool to start auction\n * @param accessControlManager_ AccessControlManager contract address\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when risk fund address is zero\n */\n function initialize(\n IRiskFund riskFund_,\n uint256 minimumPoolBadDebt_,\n address accessControlManager_\n ) external initializer {\n ensureNonzeroAddress(address(riskFund_));\n require(minimumPoolBadDebt_ != 0, \"invalid minimum pool bad debt\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n __ReentrancyGuard_init();\n __TokenDebtTracker_init();\n minimumPoolBadDebt = minimumPoolBadDebt_;\n riskFund = riskFund_;\n waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER;\n nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_LIMIT;\n incentiveBps = DEFAULT_INCENTIVE_BPS;\n auctionsPaused = false;\n }\n\n /**\n * @notice Place a bid greater than the previous in an ongoing auction\n * @param comptroller Comptroller address of the pool\n * @param bidBps The bid percent of the risk fund or bad debt depending on auction type\n * @param auctionStartBlock The block number when auction started\n * @custom:event Emits BidPlaced event on success\n */\n function placeBid(address comptroller, uint256 bidBps, uint256 auctionStartBlock) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(auction.startBlock == auctionStartBlock, \"auction has been restarted\");\n require(_isStarted(auction), \"no on-going auction\");\n require(!_isStale(auction), \"auction is stale, restart it\");\n require(bidBps > 0, \"basis points cannot be zero\");\n require(bidBps <= MAX_BPS, \"basis points cannot be more than 10000\");\n require(\n (auction.auctionType == AuctionType.LARGE_POOL_DEBT &&\n ((auction.highestBidder != address(0) && bidBps > auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps >= auction.startBidBps))) ||\n (auction.auctionType == AuctionType.LARGE_RISK_FUND &&\n ((auction.highestBidder != address(0) && bidBps < auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps <= auction.startBidBps))),\n \"your bid is not the highest\"\n );\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n if (auction.highestBidder != address(0)) {\n _transferOutOrTrackDebt(erc20, auction.highestBidder, auction.bidAmount[auction.markets[i]]);\n }\n uint256 balanceBefore = erc20.balanceOf(address(this));\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n uint256 currentBidAmount = ((auction.marketDebt[auction.markets[i]] * bidBps) / MAX_BPS);\n erc20.safeTransferFrom(msg.sender, address(this), currentBidAmount);\n } else {\n erc20.safeTransferFrom(msg.sender, address(this), auction.marketDebt[auction.markets[i]]);\n }\n\n uint256 balanceAfter = erc20.balanceOf(address(this));\n auction.bidAmount[auction.markets[i]] = balanceAfter - balanceBefore;\n }\n\n auction.highestBidder = msg.sender;\n auction.highestBidBps = bidBps;\n auction.highestBidBlock = block.number;\n\n emit BidPlaced(comptroller, auction.startBlock, bidBps, msg.sender);\n }\n\n /**\n * @notice Close an auction\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionClosed event on successful close\n */\n function closeAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(_isStarted(auction), \"no on-going auction\");\n require(\n block.number > auction.highestBidBlock + nextBidderBlockLimit && auction.highestBidder != address(0),\n \"waiting for next bidder. cannot close auction\"\n );\n\n uint256 marketsCount = auction.markets.length;\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n\n auction.status = AuctionStatus.ENDED;\n\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n uint256 balanceBefore = erc20.balanceOf(address(auction.markets[i]));\n erc20.safeTransfer(address(auction.markets[i]), auction.bidAmount[auction.markets[i]]);\n uint256 balanceAfter = erc20.balanceOf(address(auction.markets[i]));\n marketsDebt[i] = balanceAfter - balanceBefore;\n\n auction.markets[i].badDebtRecovered(marketsDebt[i]);\n }\n\n uint256 riskFundBidAmount;\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n riskFundBidAmount = auction.seizedRiskFund;\n } else {\n riskFundBidAmount = (auction.seizedRiskFund * auction.highestBidBps) / MAX_BPS;\n }\n\n address convertibleBaseAsset = riskFund.convertibleBaseAsset();\n\n uint256 transferredAmount = riskFund.transferReserveForAuction(comptroller, riskFundBidAmount);\n _transferOutOrTrackDebt(IERC20Upgradeable(convertibleBaseAsset), auction.highestBidder, riskFundBidAmount);\n\n emit AuctionClosed(\n comptroller,\n auction.startBlock,\n auction.highestBidder,\n auction.highestBidBps,\n transferredAmount,\n auction.markets,\n marketsDebt\n );\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionStarted event on success\n * @custom:event Errors if auctions are paused\n */\n function startAuction(address comptroller) external nonReentrant {\n require(!auctionsPaused, \"Auctions are paused\");\n _startAuction(comptroller);\n }\n\n /**\n * @notice Restart an auction\n * @param comptroller Address of the pool\n * @custom:event Emits AuctionRestarted event on successful restart\n */\n function restartAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(!auctionsPaused, \"auctions are paused\");\n require(_isStarted(auction), \"no on-going auction\");\n require(_isStale(auction), \"you need to wait for more time for first bidder\");\n\n auction.status = AuctionStatus.ENDED;\n\n emit AuctionRestarted(comptroller, auction.startBlock);\n _startAuction(comptroller);\n }\n\n /**\n * @notice Update next bidder block limit which is used determine when an auction can be closed\n * @param _nextBidderBlockLimit New next bidder block limit\n * @custom:event Emits NextBidderBlockLimitUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateNextBidderBlockLimit(uint256 _nextBidderBlockLimit) external {\n _checkAccessAllowed(\"updateNextBidderBlockLimit(uint256)\");\n require(_nextBidderBlockLimit != 0, \"_nextBidderBlockLimit must not be 0\");\n uint256 oldNextBidderBlockLimit = nextBidderBlockLimit;\n nextBidderBlockLimit = _nextBidderBlockLimit;\n emit NextBidderBlockLimitUpdated(oldNextBidderBlockLimit, _nextBidderBlockLimit);\n }\n\n /**\n * @notice Updates the incentive BPS\n * @param _incentiveBps New incentive BPS\n * @custom:event Emits IncentiveBpsUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateIncentiveBps(uint256 _incentiveBps) external {\n _checkAccessAllowed(\"updateIncentiveBps(uint256)\");\n require(_incentiveBps != 0, \"incentiveBps must not be 0\");\n uint256 oldIncentiveBps = incentiveBps;\n incentiveBps = _incentiveBps;\n emit IncentiveBpsUpdated(oldIncentiveBps, _incentiveBps);\n }\n\n /**\n * @notice Update minimum pool bad debt to start auction\n * @param _minimumPoolBadDebt Minimum bad debt in the base asset for a pool to start auction\n * @custom:event Emits MinimumPoolBadDebtUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateMinimumPoolBadDebt(uint256 _minimumPoolBadDebt) external {\n _checkAccessAllowed(\"updateMinimumPoolBadDebt(uint256)\");\n uint256 oldMinimumPoolBadDebt = minimumPoolBadDebt;\n minimumPoolBadDebt = _minimumPoolBadDebt;\n emit MinimumPoolBadDebtUpdated(oldMinimumPoolBadDebt, _minimumPoolBadDebt);\n }\n\n /**\n * @notice Update wait for first bidder block count. If the first bid is not made within this limit, the auction is closed and needs to be restarted\n * @param _waitForFirstBidder New wait for first bidder block count\n * @custom:event Emits WaitForFirstBidderUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateWaitForFirstBidder(uint256 _waitForFirstBidder) external {\n _checkAccessAllowed(\"updateWaitForFirstBidder(uint256)\");\n uint256 oldWaitForFirstBidder = waitForFirstBidder;\n waitForFirstBidder = _waitForFirstBidder;\n emit WaitForFirstBidderUpdated(oldWaitForFirstBidder, _waitForFirstBidder);\n }\n\n /**\n * @notice Update the pool registry this shortfall supports\n * @dev After Pool Registry is deployed we need to set the pool registry address\n * @param poolRegistry_ Address of pool registry contract\n * @custom:event Emits PoolRegistryUpdated on success\n * @custom:access Restricted to owner\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function updatePoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Pause auctions. This disables starting new auctions but lets the current auction finishes\n * @custom:event Emits AuctionsPaused on success\n * @custom:error Errors is auctions are paused\n * @custom:access Restricted by ACM\n */\n function pauseAuctions() external {\n _checkAccessAllowed(\"pauseAuctions()\");\n require(!auctionsPaused, \"Auctions are already paused\");\n auctionsPaused = true;\n emit AuctionsPaused(msg.sender);\n }\n\n /**\n * @notice Resume paused auctions.\n * @custom:event Emits AuctionsResumed on success\n * @custom:error Errors is auctions are active\n * @custom:access Restricted by ACM\n */\n function resumeAuctions() external {\n _checkAccessAllowed(\"resumeAuctions()\");\n require(auctionsPaused, \"Auctions are not paused\");\n auctionsPaused = false;\n emit AuctionsResumed(msg.sender);\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n */\n function _startAuction(address comptroller) internal {\n PoolRegistryInterface.VenusPool memory pool = PoolRegistry(poolRegistry).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n\n Auction storage auction = auctions[comptroller];\n require(\n auction.status == AuctionStatus.NOT_STARTED || auction.status == AuctionStatus.ENDED,\n \"auction is on-going\"\n );\n\n auction.highestBidBps = 0;\n auction.highestBidBlock = 0;\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = auction.markets[i];\n auction.marketDebt[vToken] = 0;\n }\n\n delete auction.markets;\n\n VToken[] memory vTokens = _getAllMarkets(comptroller);\n marketsCount = vTokens.length;\n ResilientOracleInterface priceOracle = _getPriceOracle(comptroller);\n uint256 poolBadDebt;\n\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n auction.markets = new VToken[](marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n uint256 marketBadDebt = vTokens[i].badDebt();\n\n priceOracle.updatePrice(address(vTokens[i]));\n uint256 usdValue = (priceOracle.getUnderlyingPrice(address(vTokens[i])) * marketBadDebt) / EXP_SCALE;\n\n poolBadDebt = poolBadDebt + usdValue;\n auction.markets[i] = vTokens[i];\n auction.marketDebt[vTokens[i]] = marketBadDebt;\n marketsDebt[i] = marketBadDebt;\n }\n\n require(poolBadDebt >= minimumPoolBadDebt, \"pool bad debt is too low\");\n\n priceOracle.updateAssetPrice(riskFund.convertibleBaseAsset());\n uint256 riskFundBalance = (priceOracle.getPrice(riskFund.convertibleBaseAsset()) *\n riskFund.getPoolsBaseAssetReserves(comptroller)) / EXP_SCALE;\n uint256 remainingRiskFundBalance = riskFundBalance;\n uint256 badDebtPlusIncentive = poolBadDebt + ((poolBadDebt * incentiveBps) / MAX_BPS);\n if (badDebtPlusIncentive >= riskFundBalance) {\n auction.startBidBps =\n (MAX_BPS * MAX_BPS * remainingRiskFundBalance) /\n (poolBadDebt * (MAX_BPS + incentiveBps));\n remainingRiskFundBalance = 0;\n auction.auctionType = AuctionType.LARGE_POOL_DEBT;\n } else {\n uint256 maxSeizeableRiskFundBalance = badDebtPlusIncentive;\n\n remainingRiskFundBalance = remainingRiskFundBalance - maxSeizeableRiskFundBalance;\n auction.auctionType = AuctionType.LARGE_RISK_FUND;\n auction.startBidBps = MAX_BPS;\n }\n\n auction.seizedRiskFund = riskFundBalance - remainingRiskFundBalance;\n auction.startBlock = block.number;\n auction.status = AuctionStatus.STARTED;\n auction.highestBidder = address(0);\n\n emit AuctionStarted(\n comptroller,\n auction.startBlock,\n auction.auctionType,\n auction.markets,\n marketsDebt,\n auction.seizedRiskFund,\n auction.startBidBps\n );\n }\n\n /**\n * @dev Returns the price oracle of the pool\n * @param comptroller Address of the pool's comptroller\n * @return oracle The pool's price oracle\n */\n function _getPriceOracle(address comptroller) internal view returns (ResilientOracleInterface) {\n return ResilientOracleInterface(ComptrollerViewInterface(comptroller).oracle());\n }\n\n /**\n * @dev Returns all markets of the pool\n * @param comptroller Address of the pool's comptroller\n * @return markets The pool's markets as VToken array\n */\n function _getAllMarkets(address comptroller) internal view returns (VToken[] memory) {\n return ComptrollerInterface(comptroller).getAllMarkets();\n }\n\n /**\n * @dev Checks if the auction has started\n * @param auction The auction to query the status for\n * @return True if the auction has started\n */\n function _isStarted(Auction storage auction) internal view returns (bool) {\n return auction.status == AuctionStatus.STARTED;\n }\n\n /**\n * @dev Checks if the auction is stale, i.e. there's no bidder and the auction\n * was started more than waitForFirstBidder blocks ago.\n * @param auction The auction to query the status for\n * @return True if the auction is stale\n */\n function _isStale(Auction storage auction) internal view returns (bool) {\n bool noBidder = auction.highestBidder == address(0);\n return noBidder && (block.number > auction.startBlock + waitForFirstBidder);\n }\n}\n" + }, + "contracts/test/ComptrollerHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\ncontract ComptrollerHarness is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function harnessFastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n}\n\ncontract EchoTypesComptroller {\n function stringy(string memory s) public pure returns (string memory) {\n return s;\n }\n\n function addresses(address a) public pure returns (address) {\n return a;\n }\n\n function booly(bool b) public pure returns (bool) {\n return b;\n }\n\n function listOInts(uint256[] memory u) public pure returns (uint256[] memory) {\n return u;\n }\n\n function reverty() public pure {\n require(false, \"gotcha sucka\");\n }\n}\n" + }, + "contracts/test/ComptrollerScenario.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\n\ncontract ComptrollerScenario is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function fastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n\n function unlist(VToken vToken) public {\n markets[address(vToken)].isListed = false;\n }\n\n function membershipLength(VToken vToken) public view returns (uint256) {\n return accountAssets[address(vToken)].length;\n }\n}\n" + }, + "contracts/test/ERC20.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeMath } from \"./SafeMath.sol\";\n\ninterface ERC20Base {\n event Approval(address indexed owner, address indexed spender, uint256 value);\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n function approve(address spender, uint256 value) external returns (bool);\n\n function totalSupply() external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function balanceOf(address who) external view returns (uint256);\n}\n\nabstract contract ERC20 is ERC20Base {\n function transfer(address to, uint256 value) external virtual returns (bool);\n\n function transferFrom(address from, address to, uint256 value) external virtual returns (bool);\n}\n\nabstract contract ERC20NS is ERC20Base {\n function transfer(address to, uint256 value) external virtual;\n\n function transferFrom(address from, address to, uint256 value) external virtual;\n}\n\n/**\n * @title Standard ERC20 token\n * @dev Implementation of the basic standard token.\n * See https://github.com/ethereum/EIPs/issues/20\n */\ncontract StandardToken is ERC20 {\n using SafeMath for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public override totalSupply;\n mapping(address => mapping(address => uint256)) public override allowance;\n mapping(address => uint256) public override balanceOf;\n\n constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external virtual override returns (bool) {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external virtual override returns (bool) {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n\n function approve(address _spender, uint256 amount) external virtual override returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\n/**\n * @title Non-Standard ERC20 token\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ncontract NonStandardToken is ERC20NS {\n using SafeMath for uint256;\n\n string public name;\n uint8 public decimals;\n string public symbol;\n uint256 public override totalSupply;\n mapping(address => mapping(address => uint256)) public override allowance;\n mapping(address => uint256) public override balanceOf;\n\n constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external override {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n }\n\n function transferFrom(address src, address dst, uint256 amount) external override {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n }\n\n function approve(address _spender, uint256 amount) external override returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\ncontract ERC20Harness is StandardToken {\n using SafeMath for uint256;\n // To support testing, we can specify addresses for which transferFrom should fail and return false\n mapping(address => bool) public failTransferFromAddresses;\n\n // To support testing, we allow the contract to always fail `transfer`.\n mapping(address => bool) public failTransferToAddresses;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function transfer(address dst, uint256 amount) external override returns (bool success) {\n // Added for testing purposes\n if (failTransferToAddresses[dst]) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool success) {\n // Added for testing purposes\n if (failTransferFromAddresses[src]) {\n return false;\n }\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n\n function harnessSetFailTransferFromAddress(address src, bool _fail) public {\n failTransferFromAddresses[src] = _fail;\n }\n\n function harnessSetFailTransferToAddress(address dst, bool _fail) public {\n failTransferToAddresses[dst] = _fail;\n }\n\n function harnessSetBalance(address _account, uint256 _amount) public {\n balanceOf[_account] = _amount;\n }\n}\n" + }, + "contracts/test/EvilToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { FaucetToken } from \"./FaucetToken.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title The Compound Evil Test Token\n * @author Compound\n * @notice A simple test token that fails certain operations\n */\ncontract EvilToken is FaucetToken {\n using SafeMath for uint256;\n\n bool public fail;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n fail = true;\n }\n\n function setFail(bool _fail) external {\n fail = _fail;\n }\n\n function transfer(address dst, uint256 amount) external override returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/FaucetToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { StandardToken, NonStandardToken } from \"./ERC20.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title The Compound Faucet Test Token\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetToken is StandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Compound Faucet Test Token (non-standard)\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetNonStandardToken is NonStandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n NonStandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Compound Faucet Re-Entrant Test Token\n * @author Compound\n * @notice A test token that is malicious and tries to re-enter callers\n */\ncontract FaucetTokenReEntrantHarness {\n using SafeMath for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 private totalSupply_;\n mapping(address => mapping(address => uint256)) private allowance_;\n mapping(address => uint256) private balanceOf_;\n\n bytes public reEntryCallData;\n string public reEntryFun;\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n modifier reEnter(string memory funName) {\n string memory _reEntryFun = reEntryFun;\n if (compareStrings(_reEntryFun, funName)) {\n reEntryFun = \"\"; // Clear re-entry fun\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = msg.sender.call(reEntryCallData);\n // solhint-disable-next-line no-inline-assembly\n assembly {\n if eq(success, 0) {\n revert(add(returndata, 0x20), returndatasize())\n }\n }\n }\n\n _;\n }\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n bytes memory _reEntryCallData,\n string memory _reEntryFun\n ) {\n totalSupply_ = _initialAmount;\n balanceOf_[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n reEntryCallData = _reEntryCallData;\n reEntryFun = _reEntryFun;\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf_[_owner] += value;\n totalSupply_ += value;\n emit Transfer(address(this), _owner, value);\n }\n\n function totalSupply() public reEnter(\"totalSupply\") returns (uint256) {\n return totalSupply_;\n }\n\n function allowance(address owner, address spender) public reEnter(\"allowance\") returns (uint256 remaining) {\n return allowance_[owner][spender];\n }\n\n function approve(address spender, uint256 amount) public reEnter(\"approve\") returns (bool success) {\n _approve(msg.sender, spender, amount);\n return true;\n }\n\n function balanceOf(address owner) public reEnter(\"balanceOf\") returns (uint256 balance) {\n return balanceOf_[owner];\n }\n\n function transfer(address dst, uint256 amount) public reEnter(\"transfer\") returns (bool success) {\n _transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) public reEnter(\"transferFrom\") returns (bool success) {\n _transfer(src, dst, amount);\n _approve(src, msg.sender, allowance_[src][msg.sender].sub(amount));\n return true;\n }\n\n function _approve(address owner, address spender, uint256 amount) internal {\n require(spender != address(0), \"FaucetToken: approve to the zero address\");\n require(owner != address(0), \"FaucetToken: approve from the zero address\");\n allowance_[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n function _transfer(address src, address dst, uint256 amount) internal {\n require(dst != address(0), \"FaucetToken: transfer to the zero address\");\n balanceOf_[src] = balanceOf_[src].sub(amount);\n balanceOf_[dst] = balanceOf_[dst].add(amount);\n emit Transfer(src, dst, amount);\n }\n\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)));\n }\n}\n" + }, + "contracts/test/FeeToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { FaucetToken } from \"./FaucetToken.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title Fee Token\n * @author Compound\n * @notice A simple test token that charges fees on transfer. Used to mock USDT.\n */\ncontract FeeToken is FaucetToken {\n using SafeMath for uint256;\n\n uint256 public basisPointFee;\n address public owner;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n uint256 _basisPointFee,\n address _owner\n ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n basisPointFee = _basisPointFee;\n owner = _owner;\n }\n\n function transfer(address dst, uint256 amount) public override returns (bool) {\n uint256 fee = amount.mul(basisPointFee).div(10000);\n uint256 net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) public override returns (bool) {\n uint256 fee = amount.mul(basisPointFee).div(10000);\n uint256 net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/HarnessMaxLoopsLimitHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\n\ncontract HarnessMaxLoopsLimitHelper is MaxLoopsLimitHelper {\n function setMaxLoopsLimit(uint256 limit) external {\n _setMaxLoopsLimit(limit);\n }\n\n function ensureMaxLoops(uint256 limit) external view {\n _ensureMaxLoops(limit);\n }\n}\n" + }, + "contracts/test/lib/ApproveOrRevertHarness.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ApproveOrRevert } from \"../../lib/ApproveOrRevert.sol\";\n\ncontract ApproveOrRevertHarness {\n using ApproveOrRevert for IERC20Upgradeable;\n\n function approve(IERC20Upgradeable token, address spender, uint256 amount) external {\n token.approveOrRevert(spender, amount);\n }\n}\n" + }, + "contracts/test/lib/TokenDebtTrackerHarness.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { TokenDebtTracker } from \"../../lib/TokenDebtTracker.sol\";\n\ncontract TokenDebtTrackerHarness is TokenDebtTracker {\n function initialize() external initializer {\n __TokenDebtTracker_init();\n }\n\n function addTokenDebt(IERC20Upgradeable token, address user, uint256 amount) external {\n tokenDebt[token][user] += amount;\n totalTokenDebt[token] += amount;\n }\n\n function transferOutOrTrackDebt(IERC20Upgradeable token, address user, uint256 amount) external {\n _transferOutOrTrackDebt(token, user, amount);\n }\n\n function transferOutOrTrackDebtSkippingBalanceCheck(\n IERC20Upgradeable token,\n address user,\n uint256 amount\n ) external {\n _transferOutOrTrackDebtSkippingBalanceCheck(token, user, amount);\n }\n}\n" + }, + "contracts/test/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 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(address from, address to, uint256 value) 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(address owner, address spender, uint256 value) private {\n allowance[owner][spender] = value;\n emit Approval(owner, spender, value);\n }\n\n function _transfer(address from, address to, uint256 value) 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/MockPriceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { BinanceOracle } from \"@venusprotocol/oracle/contracts/oracles/BinanceOracle.sol\";\nimport { ChainlinkOracle } from \"@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol\";\n\nimport { VToken } from \"../../VToken.sol\";\n\ncontract MockPriceOracle is ResilientOracleInterface {\n mapping(address => uint256) public assetPrices;\n\n //set price in 6 decimal precision\n // solhint-disable-next-line no-empty-blocks\n constructor() {}\n\n function setPrice(address asset, uint256 price) external {\n assetPrices[asset] = price;\n }\n\n // solhint-disable-next-line no-empty-blocks\n function updatePrice(address vToken) external override {}\n\n // solhint-disable-next-line no-empty-blocks\n function updateAssetPrice(address asset) external override {}\n\n function getPrice(address asset) external view returns (uint256) {\n return assetPrices[asset];\n }\n\n //https://compound.finance/docs/prices\n function getUnderlyingPrice(address vToken) public view override returns (uint256) {\n return assetPrices[VToken(vToken).underlying()];\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(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/test/SafeMath.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\n// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol\n// Subject to the MIT license.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c;\n unchecked {\n c = a + b;\n }\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n uint256 c;\n unchecked {\n c = a + b;\n }\n require(c >= a, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction underflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c;\n unchecked {\n c = a * b;\n }\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c;\n unchecked {\n c = a * b;\n }\n require(c / a == b, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers.\n * Reverts on division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers.\n * Reverts with custom message on division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "contracts/test/UpgradedVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\n/**\n * @title Venus's VToken Contract\n * @notice VTokens which wrap an EIP-20 underlying and are immutable\n * @author Venus\n */\ncontract UpgradedVToken is VToken {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param riskManagement Addresses of risk fund contracts\n */\n\n /// @notice We added this new function to test contract upgrade\n function version() external pure returns (uint256) {\n return 2;\n }\n\n function initializeV2(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) public reinitializer(2) {\n super._initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\n );\n }\n\n function getTokenUnderlying() public view returns (address) {\n return underlying;\n }\n}\n" + }, + "contracts/test/VTokenHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\ncontract VTokenHarness is VToken {\n uint256 public blockNumber;\n uint256 public harnessExchangeRate;\n bool public harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function harnessSetAccrualBlockNumber(uint256 accrualBlockNumber_) external {\n accrualBlockNumber = accrualBlockNumber_;\n }\n\n function harnessSetBlockNumber(uint256 newBlockNumber) external {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint256 blocks) external {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint256 amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetTotalSupply(uint256 totalSupply_) external {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint256 totalBorrows_) external {\n totalBorrows = totalBorrows_;\n }\n\n function harnessSetTotalReserves(uint256 totalReserves_) external {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint256 totalSupply_, uint256 totalBorrows_, uint256 totalReserves_) external {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint256 exchangeRate) external {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address to_, bool fail_) external {\n failTransferToAddresses[to_] = fail_;\n }\n\n function harnessMintFresh(address account, uint256 mintAmount) external {\n super._mintFresh(account, account, mintAmount);\n }\n\n function harnessRedeemFresh(address payable account, uint256 vTokenAmount, uint256 underlyingAmount) external {\n super._redeemFresh(account, vTokenAmount, underlyingAmount);\n }\n\n function harnessSetAccountBorrows(address account, uint256 principal, uint256 interestIndex) external {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint256 borrowIndex_) external {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint256 borrowAmount) external {\n _borrowFresh(account, borrowAmount);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint256 repayAmount) external {\n _repayBorrowFresh(payer, account, repayAmount);\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VToken vTokenCollateral,\n bool skipLiquidityCheck\n ) external {\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n function harnessReduceReservesFresh(uint256 amount) external {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint256 newReserveFactorMantissa) external {\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) external {\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessAccountBorrows(address account) external view returns (uint256 principal, uint256 interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function getBorrowRateMaxMantissa() external pure returns (uint256) {\n return MAX_BORROW_RATE_MANTISSA;\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModel(newInterestRateModelAddress);\n }\n\n function harnessCallPreBorrowHook(uint256 amount) public {\n comptroller.preBorrowHook(address(this), msg.sender, amount);\n }\n\n function _doTransferOut(address to, uint256 amount) internal override {\n require(failTransferToAddresses[to] == false, \"HARNESS_TOKEN_TRANSFER_OUT_FAILED\");\n return super._doTransferOut(to, amount);\n }\n\n function _exchangeRateStored() internal view override returns (uint256) {\n if (harnessExchangeRateStored) {\n return harnessExchangeRate;\n }\n return super._exchangeRateStored();\n }\n\n function _getBlockNumber() internal view override returns (uint256) {\n return blockNumber;\n }\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { IProtocolShareReserve } from \"./RiskFund/IProtocolShareReserve.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\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 /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\n );\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\n return true;\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\n return totalBorrows;\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\n _redeemFresh(msg.sender, redeemTokens, 0);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\n _redeemFresh(msg.sender, 0, redeemAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n _borrowFresh(msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\n }\n\n /**\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint256) {\n return transferAllowances[owner][spender];\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return amount The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint256) {\n return accountTokens[owner];\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return rate The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this v\n * @return rate The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\n return _exchangeRateStored();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number */\n uint256 currentBlockNumber = _getBlockNumber();\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return NO_ERROR;\n }\n\n /**\n * @notice User supplies assets into the market and receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param payer The address of the account which is sending the assets for supply\n * @param minter The address of the account which is supplying the assets\n * @param mintAmount The amount of the underlying asset to supply\n */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `_doTransferIn` for the minter and the mintAmount.\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\n\n /*\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n }\n\n /**\n * @notice User redeems vTokens in exchange for the underlying asset\n * @dev Assumes interest has already been accrued up to the current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n */\n function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\n\n /* If redeemTokensIn > 0: */\n if (redeemTokensIn > 0) {\n /*\n * We calculate the exchange rate and the amount of underlying to be redeemed:\n * redeemTokens = redeemTokensIn\n */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\n * On success, the vToken has redeemAmount less of cash.\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n _doTransferOut(redeemer, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n }\n\n /**\n * @notice Users borrow assets from the protocol to their own address\n * @param borrower User who borrows the assets\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the borrower and the borrowAmount.\n * On success, the vToken borrowAmount less of cash.\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n _doTransferOut(borrower, borrowAmount);\n\n /* We emit a Borrow event */\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\n }\n\n /**\n * @notice Borrows are repaid by another user (possibly the borrower).\n * @param payer the account paying off the borrow\n * @param borrower the account with the debt being payed off\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call _doTransferIn for the payer and the repayAmount\n * On success, the vToken holds an additional repayAmount of cash.\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\n\n /*\n * We calculate the new borrower and total borrow balances, failing on underflow:\n * accountBorrowsNew = accountBorrows - actualRepayAmount\n * totalBorrowsNew = totalBorrows - actualRepayAmount\n */\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == NO_ERROR, \"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\");\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"LIQUIDATE_SEIZE_TOO_MUCH\");\n\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\n\n /*\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\n */\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n uint256 totalReservesNew = totalReserves + protocolSeizeAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalReserves = totalReservesNew;\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit Transfer(borrower, address(this), protocolSeizeTokens);\n emit ReservesAdded(address(this), protocolSeizeAmount, totalReservesNew);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\n ComptrollerInterface oldComptroller = comptroller;\n // Ensure invoke comptroller.isComptroller() returns true\n require(newComptroller.isComptroller(), \"marker method returned false\");\n\n // Set market's comptroller to newComptroller\n comptroller = newComptroller;\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(oldComptroller, newComptroller);\n }\n\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n }\n\n /**\n * @notice Add reserves by transferring from caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n totalReservesNew = totalReserves - reduceAmount;\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(address(comptroller), underlying);\n\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert SetInterestRateModelFreshCheck();\n }\n\n // Track the market's current interest rate model\n oldInterestRateModel = interestRateModel;\n\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\n require(newInterestRateModel.isInterestRateModel(), \"marker method returned false\");\n\n // Set the interest rate model to newInterestRateModel\n interestRateModel = newInterestRateModel;\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\n }\n\n /*** Safe Token ***/\n\n /**\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n * @param from Sender of the underlying tokens\n * @param amount Amount of underlying to transfer\n * @return Actual amount received\n */\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n // Return the amount that was *actually* transferred\n return balanceAfter - balanceBefore;\n }\n\n /**\n * @dev Just a regular ERC-20 transfer, reverts on failure\n * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\n * @dev Called by both `transfer` and `transferFrom` internally\n * @param spender The address of the account performing the transfer\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param tokens The number of tokens to transfer\n */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\n if (spender == src) {\n startingAllowance = type(uint256).max;\n } else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under,over}flow */\n uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if necessary) */\n if (startingAllowance != type(uint256).max) {\n transferAllowances[src][spender] = allowanceNew;\n }\n\n /* We emit a Transfer event */\n emit Transfer(src, dst, tokens);\n }\n\n /**\n * @notice Initialize the money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n require(accrualBlockNumber == 0 && borrowIndex == 0, \"market may only be initialized once\");\n\n // Set initial exchange rate\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa > 0, \"initial exchange rate must be greater than zero.\");\n\n _setComptroller(comptroller_);\n\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\n accrualBlockNumber = _getBlockNumber();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on block number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying tokens owned by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n return token.balanceOf(address(this));\n }\n\n /**\n * @dev Function to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n * @return Current block number\n */\n function _getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\n\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\n */\n if (borrowSnapshot.principal == 0) {\n return 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\n */\n struct BorrowSnapshot {\n uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\n\n /**\n * @notice EIP-20 token name for this token\n */\n string public name;\n\n /**\n * @notice EIP-20 token symbol for this token\n */\n string public symbol;\n\n /**\n * @notice EIP-20 token decimals for this token\n */\n uint8 public decimals;\n\n /**\n * @notice Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\n\n // Maximum borrow rate that can ever be applied (.0005% / block)\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n /**\n * @notice Contract which oversees inter-vToken operations\n */\n ComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\n InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\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\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address indexed admin, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/WhitePaperInterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { EXP_SCALE, MANTISSA_ONE } from \"./lib/constants.sol\";\n\n/**\n * @title Compound's WhitePaperInterestRateModel Contract\n * @author Compound\n * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper\n */\ncontract WhitePaperInterestRateModel is InterestRateModel {\n /**\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\n */\n uint256 public immutable blocksPerYear;\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public immutable multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public immutable baseRatePerBlock;\n\n event NewInterestParams(uint256 baseRatePerBlock, uint256 multiplierPerBlock);\n\n /**\n * @notice Construct an interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n */\n constructor(uint256 blocksPerYear_, uint256 baseRatePerYear, uint256 multiplierPerYear) {\n require(blocksPerYear_ != 0, \"Invalid blocks per year\");\n baseRatePerBlock = baseRatePerYear / blocksPerYear_;\n multiplierPerBlock = multiplierPerYear / blocksPerYear_;\n blocksPerYear = blocksPerYear_;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock);\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public view override returns (uint256) {\n uint256 ur = utilizationRate(cash, borrows, reserves, badDebt);\n return ((ur * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) public view override returns (uint256) {\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\n uint256 borrowRate = getBorrowRate(cash, borrows, reserves, badDebt);\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\n uint256 incomeToDistribute = borrows * rateToPool;\n uint256 supply = cash + borrows + badDebt - reserves;\n return incomeToDistribute / supply;\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @param badDebt The amount of badDebt in the market\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\n */\n function utilizationRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows and badDebt\n if ((borrows + badDebt) == 0) {\n return 0;\n }\n\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\n\n if (rate > EXP_SCALE) {\n rate = EXP_SCALE;\n }\n\n return rate;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/sepolia/solcInputs/8249036c2fd27f6f9b40677e2c950aaf.json b/deployments/sepolia/solcInputs/8249036c2fd27f6f9b40677e2c950aaf.json new file mode 100644 index 000000000..21b10dffa --- /dev/null +++ b/deployments/sepolia/solcInputs/8249036c2fd27f6f9b40677e2c950aaf.json @@ -0,0 +1,285 @@ +{ + "language": "Solidity", + "sources": { + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "@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/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.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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 Venus Access Control Contract.\n * @dev The AccessControlledV8 contract is a wrapper around the OpenZeppelin AccessControl contract\n * It provides a standardized way to control access to methods within the Venus Smart Contract Ecosystem.\n * The contract allows the owner to set an AccessControlManager contract address.\n * It can restrict method calls based on the sender's role and the method's signature.\n */\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/AccessControlManager.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title Venus Access Control Contract\n * @author venus\n * @dev This contract is a wrapper of OpenZeppelin AccessControl\n *\t\textending it in a way to standartize access control\n *\t\twithin Venus Smart Contract Ecosystem\n */\ncontract AccessControlManager is AccessControl, IAccessControlManagerV8 {\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(address contractAddress, string calldata functionSig, address accountToPermit) 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 calldata 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 calldata 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 calldata functionSig\n ) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n return hasRole(role, account);\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\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/FeedRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface FeedRegistryInterface {\n function latestRoundDataByName(\n string memory base,\n string memory quote\n )\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n function decimalsByName(string memory base, string memory quote) external view returns (uint8);\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/PublicResolverInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\ninterface PublicResolverInterface {\n function addr(bytes32 node) external view returns (address payable);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/SIDRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\ninterface SIDRegistryInterface {\n function resolver(bytes32 node) external view returns (address);\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/oracles/BinanceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/SIDRegistryInterface.sol\";\nimport \"../interfaces/FeedRegistryInterface.sol\";\nimport \"../interfaces/PublicResolverInterface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport \"../interfaces/OracleInterface.sol\";\n\n/**\n * @title BinanceOracle\n * @author Venus\n * @notice This oracle fetches price of assets from Binance.\n */\ncontract BinanceOracle is AccessControlledV8, OracleInterface {\n address public sidRegistryAddress;\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Max stale period configuration for assets\n mapping(string => uint256) public maxStalePeriod;\n\n /// @notice Override symbols to be compatible with Binance feed registry\n mapping(string => string) public symbols;\n\n event MaxStalePeriodAdded(string indexed asset, uint256 maxStalePeriod);\n\n event SymbolOverridden(string indexed symbol, string overriddenSymbol);\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 /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Used to set the max stale period of an asset\n * @param symbol The symbol of the asset\n * @param _maxStalePeriod The max stake period\n */\n function setMaxStalePeriod(string memory symbol, uint256 _maxStalePeriod) external {\n _checkAccessAllowed(\"setMaxStalePeriod(string,uint256)\");\n if (_maxStalePeriod == 0) revert(\"stale period can't be zero\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n maxStalePeriod[symbol] = _maxStalePeriod;\n emit MaxStalePeriodAdded(symbol, _maxStalePeriod);\n }\n\n /**\n * @notice Used to override a symbol when fetching price\n * @param symbol The symbol to override\n * @param overrideSymbol The symbol after override\n */\n function setSymbolOverride(string calldata symbol, string calldata overrideSymbol) external {\n _checkAccessAllowed(\"setSymbolOverride(string,string)\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n symbols[symbol] = overrideSymbol;\n emit SymbolOverridden(symbol, overrideSymbol);\n }\n\n /**\n * @notice Sets the contracts required to fetch prices\n * @param _sidRegistryAddress Address of SID registry\n * @param _accessControlManager Address of the access control manager contract\n */\n function initialize(\n address _sidRegistryAddress,\n address _accessControlManager\n ) external initializer notNullAddress(_sidRegistryAddress) {\n sidRegistryAddress = _sidRegistryAddress;\n __AccessControlled_init(_accessControlManager);\n }\n\n /**\n * @notice Uses Space ID to fetch the feed registry address\n * @return feedRegistryAddress Address of binance oracle feed registry.\n */\n function getFeedRegistryAddress() public view returns (address) {\n bytes32 nodeHash = 0x94fe3821e0768eb35012484db4df61890f9a6ca5bfa984ef8ff717e73139faff;\n\n SIDRegistryInterface sidRegistry = SIDRegistryInterface(sidRegistryAddress);\n address publicResolverAddress = sidRegistry.resolver(nodeHash);\n PublicResolverInterface publicResolver = PublicResolverInterface(publicResolverAddress);\n\n return publicResolver.addr(nodeHash);\n }\n\n /**\n * @notice Gets the price of a asset from the binance oracle\n * @param asset Address of the asset\n * @return Price in USD\n */\n function getPrice(address asset) public view returns (uint256) {\n string memory symbol;\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n symbol = \"BNB\";\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n symbol = token.symbol();\n decimals = token.decimals();\n }\n\n string memory overrideSymbol = symbols[symbol];\n\n if (bytes(overrideSymbol).length != 0) {\n symbol = overrideSymbol;\n }\n\n return _getPrice(symbol, decimals);\n }\n\n function _getPrice(string memory symbol, uint256 decimals) internal view returns (uint256) {\n FeedRegistryInterface feedRegistry = FeedRegistryInterface(getFeedRegistryAddress());\n\n (, int256 answer, , uint256 updatedAt, ) = feedRegistry.latestRoundDataByName(symbol, \"USD\");\n if (answer <= 0) revert(\"invalid binance oracle price\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n if (deltaTime > maxStalePeriod[symbol]) revert(\"binance oracle price expired\");\n\n uint256 decimalDelta = feedRegistry.decimalsByName(symbol, \"USD\");\n return (uint256(answer) * (10 ** (18 - decimalDelta))) * (10 ** (18 - decimals));\n }\n}\n" + }, + "@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ChainlinkOracle\n * @author Venus\n * @notice This oracle fetches prices of assets from the Chainlink oracle.\n */\ncontract ChainlinkOracle is AccessControlledV8, OracleInterface {\n struct TokenConfig {\n /// @notice Underlying token address, which can't be a null address\n /// @notice Used to check if a token is supported\n /// @notice 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB for BNB\n address asset;\n /// @notice Chainlink feed address\n address feed;\n /// @notice Price expiration period of this asset\n uint256 maxStalePeriod;\n }\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Manually set an override price, useful under extenuating conditions such as price feed failure\n mapping(address => uint256) public prices;\n\n /// @notice Token config by assets\n mapping(address => TokenConfig) public tokenConfigs;\n\n /// @notice Emit when a price is manually set\n event PricePosted(address indexed asset, uint256 previousPriceMantissa, uint256 newPriceMantissa);\n\n /// @notice Emit when a token config is added\n event TokenConfigAdded(address indexed asset, address feed, uint256 maxStalePeriod);\n\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Manually set the price of a given asset\n * @param asset Asset address\n * @param price Asset price in 18 decimals\n * @custom:access Only Governance\n * @custom:event Emits PricePosted event on succesfully setup of asset price\n */\n function setDirectPrice(address asset, uint256 price) external notNullAddress(asset) {\n _checkAccessAllowed(\"setDirectPrice(address,uint256)\");\n\n uint256 previousPriceMantissa = prices[asset];\n prices[asset] = price;\n emit PricePosted(asset, previousPriceMantissa, price);\n }\n\n /**\n * @notice Add multiple token configs at the same time\n * @param tokenConfigs_ config array\n * @custom:access Only Governance\n * @custom:error Zero length error thrown, if length of the array in parameter 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 Initializes the owner of the contract\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n }\n\n /**\n * @notice Add single token config. asset & feed cannot be null addresses and maxStalePeriod must be positive\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error NotNullAddress error is thrown if token feed address is null\n * @custom:error Range error is thrown if maxStale period of token is not greater than zero\n * @custom:event Emits TokenConfigAdded event on succesfully setting of the token config\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.feed) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n if (tokenConfig.maxStalePeriod == 0) revert(\"stale period can't be zero\");\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(tokenConfig.asset, tokenConfig.feed, tokenConfig.maxStalePeriod);\n }\n\n /**\n * @notice Gets the price of a asset from the chainlink oracle\n * @param asset Address of the asset\n * @return Price in USD from Chainlink or a manually set price for the asset\n */\n function getPrice(address asset) public view returns (uint256) {\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n decimals = token.decimals();\n }\n\n return _getPriceInternal(asset, decimals);\n }\n\n /**\n * @notice Gets the Chainlink price for a given asset\n * @param asset address of the asset\n * @param decimals decimals of the asset\n * @return price Asset price in USD or a manually set price of the asset\n */\n function _getPriceInternal(address asset, uint256 decimals) internal view returns (uint256 price) {\n uint256 tokenPrice = prices[asset];\n if (tokenPrice != 0) {\n price = tokenPrice;\n } else {\n price = _getChainlinkPrice(asset);\n }\n\n uint256 decimalDelta = 18 - decimals;\n return price * (10 ** decimalDelta);\n }\n\n /**\n * @notice Get the Chainlink price for an asset, revert if token config doesn't exist\n * @dev The precision of the price feed is used to ensure the returned price has 18 decimals of precision\n * @param asset Address of the asset\n * @return price Price in USD, with 18 decimals of precision\n * @custom:error NotNullAddress error is thrown if the asset address is null\n * @custom:error Price error is thrown if the Chainlink price of asset is not greater than zero\n * @custom:error Timing error is thrown if current timestamp is less than the last updatedAt timestamp\n * @custom:error Timing error is thrown if time difference between current time and last updated time\n * is greater than maxStalePeriod\n */\n function _getChainlinkPrice(\n address asset\n ) private view notNullAddress(tokenConfigs[asset].asset) returns (uint256) {\n TokenConfig memory tokenConfig = tokenConfigs[asset];\n AggregatorV3Interface feed = AggregatorV3Interface(tokenConfig.feed);\n\n // note: maxStalePeriod cannot be 0\n uint256 maxStalePeriod = tokenConfig.maxStalePeriod;\n\n // Chainlink USD-denominated feeds store answers at 8 decimals, mostly\n uint256 decimalDelta = 18 - feed.decimals();\n\n (, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData();\n if (answer <= 0) revert(\"chainlink price must be positive\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n\n if (deltaTime > maxStalePeriod) revert(\"chainlink price expired\");\n\n return uint256(answer) * (10 ** decimalDelta);\n }\n}\n" + }, + "contracts/BaseJumpRateModelV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { EXP_SCALE, MANTISSA_ONE } from \"./lib/constants.sol\";\n\n/**\n * @title Logic for Compound's JumpRateModel Contract V2.\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\n */\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\n /**\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\n */\n uint256 public immutable blocksPerYear;\n /**\n * @notice The address of the AccessControlManager contract\n */\n IAccessControlManagerV8 public accessControlManager;\n\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public baseRatePerBlock;\n\n /**\n * @notice The multiplier per block after hitting a specified utilization point\n */\n uint256 public jumpMultiplierPerBlock;\n\n /**\n * @notice The utilization point at which the jump multiplier is applied\n */\n uint256 public kink;\n\n event NewInterestParams(\n uint256 baseRatePerBlock,\n uint256 multiplierPerBlock,\n uint256 jumpMultiplierPerBlock,\n uint256 kink\n );\n\n /**\n * @notice Thrown when the action is prohibited by AccessControlManager\n */\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n /**\n * @notice Construct an interest rate model\n * @param blocksPerYear_ The approximate number of blocks per year that is assumed by the interest rate model.\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n * @param accessControlManager_ The address of the AccessControlManager contract\n */\n constructor(\n uint256 blocksPerYear_,\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_,\n IAccessControlManagerV8 accessControlManager_\n ) {\n require(address(accessControlManager_) != address(0), \"invalid ACM address\");\n require(blocksPerYear_ != 0, \"Invalid blocks per year\");\n accessControlManager = accessControlManager_;\n blocksPerYear = blocksPerYear_;\n\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\n }\n\n /**\n * @notice Update the parameters of the interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n * @custom:error Unauthorized if the sender is not allowed to call this function\n * @custom:access Controlled by AccessControlManager\n */\n function updateJumpRateModel(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_\n ) external virtual {\n string memory signature = \"updateJumpRateModel(uint256,uint256,uint256,uint256)\";\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) public view virtual override returns (uint256) {\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\n uint256 incomeToDistribute = borrows * rateToPool;\n uint256 supply = cash + borrows + badDebt - reserves;\n return incomeToDistribute / supply;\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @param badDebt The amount of badDebt in the market\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\n */\n function utilizationRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows and badDebt\n if ((borrows + badDebt) == 0) {\n return 0;\n }\n\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\n\n if (rate > EXP_SCALE) {\n rate = EXP_SCALE;\n }\n\n return rate;\n }\n\n /**\n * @notice Internal function to update the parameters of the interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n */\n function _updateJumpRateModel(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_\n ) internal {\n baseRatePerBlock = baseRatePerYear / blocksPerYear;\n multiplierPerBlock = multiplierPerYear / blocksPerYear;\n jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear;\n kink = kink_;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function _getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) internal view returns (uint256) {\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\n uint256 kink_ = kink;\n\n if (util <= kink_) {\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n }\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n uint256 excessUtil;\n unchecked {\n excessUtil = util - kink_;\n }\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\n }\n}\n" + }, + "contracts/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\n\n /// @notice Emitted when a collateral factor is changed by admin\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\n );\n\n /// @notice Emitted when liquidation incentive is changed by admin\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\n\n /// @notice Emitted when borrow cap for a vToken is changed\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\n\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\n\n /// @notice Emitted when supply cap for a vToken is changed\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\n\n /// @notice Emitted when a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\n\n /// @notice Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow.\n * @param vTokenAddress The address of the asset to be removed\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\n\n Market storage marketToExit = markets[address(vToken)];\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return NO_ERROR;\n }\n\n /* Set vToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete vToken from the account’s list of assets */\n // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\n\n /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param vToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(\n address vToken,\n address minter,\n uint256 mintAmount\n ) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param vToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(\n address vToken,\n address redeemer,\n uint256 redeemTokens\n ) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param vToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(\n address vToken,\n address borrower,\n uint256 borrowAmount\n ) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param vToken The market to verify the repay against\n * @param borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if the market is deprecated or it is a forced liquidation */\n if (skipLiquidityCheck || isDeprecated(VToken(vTokenBorrowed))) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\n }\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param vToken The market to verify the transfer against\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external override {\n _checkActionPauseState(vToken, Action.TRANSFER);\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = accountAssets[user];\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = accountAssets[borrower];\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\n // Set liquidation incentive to new incentive\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n // Emit event with old incentive, new incentive\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"setMarketBorrowCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \"invalid input\");\n\n _ensureMaxLoops(numMarkets);\n\n for (uint256 i; i < numMarkets; ++i) {\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\n }\n }\n\n /**\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(\n VToken[] calldata marketsList,\n Action[] calldata actionsList,\n bool paused\n ) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(address account)\n external\n view\n returns (\n uint256 error,\n uint256 liquidity,\n uint256 shortfall\n )\n {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(address account)\n external\n view\n returns (\n uint256 error,\n uint256 liquidity,\n uint256 shortfall\n )\n {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall Hypothetical account shortfall below collateral requirements\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n )\n external\n view\n returns (\n uint256 error,\n uint256 liquidity,\n uint256 shortfall\n )\n {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market.\n * @return markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\n }\n\n /**\n * @notice Check if a market is marked as listed (active)\n * @param vToken vToken Address for the market to check\n * @return listed True if listed otherwise false\n */\n function isMarketListed(VToken vToken) external view returns (bool) {\n return markets[address(vToken)].isListed;\n }\n\n /*** Assets You Are In ***/\n\n /**\n * @notice Returns the assets an account has entered\n * @param account The address of the account to pull assets for\n * @return A list with the assets the account has entered\n */\n function getAssetsIn(address account) external view returns (VToken[] memory) {\n VToken[] memory assetsIn = accountAssets[account];\n\n return assetsIn;\n }\n\n /**\n * @notice Returns whether the given account is entered in a given market\n * @param account The address of the account to check\n * @param vToken The vToken to check\n * @return True if the account is in the market specified, otherwise false.\n */\n function checkMembership(address account, VToken vToken) external view returns (bool) {\n return markets[address(vToken)].accountMembership[account];\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = accountAssets[account];\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\n }\n\n /**\n * @notice Check if a vToken market has been deprecated\n * @dev All borrows in a deprecated vToken market can be immediately liquidated\n * @param vToken The market to check if deprecated\n * @return deprecated True if the given vToken market has been deprecated\n */\n function isDeprecated(VToken vToken) public view returns (bool) {\n return\n markets[address(vToken)].collateralFactorMantissa == 0 &&\n actionPaused(address(vToken), Action.BORROW) &&\n vToken.reserveFactorMantissa() == MANTISSA_ONE;\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param vToken The market to enter\n * @param borrower The address of the account to modify\n */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\n\n // survived the gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n accountAssets[borrower].push(vToken);\n\n emit MarketEntered(vToken, borrower);\n }\n\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\n }\n\n /**\n * @dev Pause/unpause an action on a market\n * @param market Market to pause/unpause the action on\n * @param action Action id to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n */\n function _setActionPaused(\n address market,\n Action action,\n bool paused\n ) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(\n address vToken,\n address redeemer,\n uint256 redeemTokens\n ) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(address account, function(VToken) internal view returns (Exp memory) weight)\n internal\n view\n returns (AccountLiquiditySnapshot memory snapshot)\n {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = accountAssets[account];\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(VToken vToken, address user)\n internal\n view\n returns (\n uint256 vTokenBalance,\n uint256 borrowBalance,\n uint256 exchangeRateMantissa\n )\n {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\n\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(\n address vToken,\n address minter,\n uint256 mintAmount\n ) external;\n\n function preRedeemHook(\n address vToken,\n address redeemer,\n uint256 redeemTokens\n ) external;\n\n function preBorrowHook(\n address vToken,\n address borrower,\n uint256 borrowAmount\n ) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function preTransferHook(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // Multiplier representing the most one can borrow against their collateral in this market.\n // For instance, 0.9 to allow borrowing 90% of collateral value.\n // Must be between 0 and 1, and stored as a mantissa.\n uint256 collateralFactorMantissa;\n // Multiplier representing the collateralization after which the borrow is eligible\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\n // value. Must be between 0 and collateral factor, stored as a mantissa.\n uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\n enum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n }\n\n /**\n * @notice Oracle which gives the price of any given asset\n */\n ResilientOracleInterface public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\n uint256 public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives\n */\n uint256 public liquidationIncentiveMantissa;\n\n /**\n * @notice Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\n\n /**\n * @notice Official mapping of vTokens -> Market metadata\n * @dev Used e.g. to determine if a market is supported\n */\n mapping(address => Market) public markets;\n\n /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\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" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Compound\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract ExponentialNoError {\n struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return truncate(product);\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(\n Exp memory a,\n uint256 scalar,\n uint256 addend\n ) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return add_(truncate(product), addend);\n }\n\n /**\n * @dev Checks if first Exp is less than second Exp.\n */\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa < right.mantissa;\n }\n\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, errorMessage);\n return uint32(n);\n }\n\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\n }\n\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), b.mantissa);\n }\n\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/IPancakeswapV2Router.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPancakeswapV2Router {\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n}\n" + }, + "contracts/JumpRateModelV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { BaseJumpRateModelV2 } from \"./BaseJumpRateModelV2.sol\";\n\n/**\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\n * @author Arr00\n * @notice Supports only for V2 vTokens\n */\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\n constructor(\n uint256 blocksPerYear_,\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_,\n IAccessControlManagerV8 accessControlManager_\n )\n BaseJumpRateModelV2(\n blocksPerYear_,\n baseRatePerYear,\n multiplierPerYear,\n jumpMultiplierPerYear,\n kink_,\n accessControlManager_\n )\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n /**\n * @notice Calculates the current borrow rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view override returns (uint256) {\n return _getBorrowRate(cash, borrows, reserves, badDebt);\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlock;\n uint256 borrowRatePerBlock;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(address poolRegistryAddress, address comptroller)\n external\n view\n returns (PoolData memory)\n {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(address poolRegistryAddress, address asset)\n external\n view\n returns (address[] memory)\n {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(VToken[] calldata vTokens)\n external\n view\n returns (VTokenUnderlyingPrice[] memory)\n {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(address account, address comptrollerAddress)\n external\n view\n returns (RewardSummary[] memory)\n {\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = comptroller.getAllMarkets();\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\n\n return\n VTokenBalances({\n vToken: address(vToken),\n balanceOf: balanceOf,\n borrowBalanceCurrent: borrowBalanceCurrent,\n balanceOfUnderlying: balanceOfUnderlying,\n tokenBalance: tokenBalance,\n tokenAllowance: tokenAllowance\n });\n }\n\n /**\n * @notice Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(address poolRegistryAddress, PoolRegistry.VenusPool memory venusPool)\n public\n view\n returns (PoolData memory)\n {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlock: vToken.supplyRatePerBlock(),\n borrowRatePerBlock: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(address(vToken.comptroller()));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n return\n VTokenUnderlyingPrice({\n vToken: address(vToken),\n underlyingPrice: priceOracle.getUnderlyingPrice(address(vToken))\n });\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n (borrowState.index, borrowState.block, borrowState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenBorrowState(address(markets[i]));\n RewardTokenState memory supplyState;\n (supplyState.index, supplyState.block, supplyState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenSupplyState(address(markets[i]));\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, borrowAmount) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: borrowState.index }), ratio);\n borrowState.index = safe224(index.mantissa, \"new index overflows\");\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(supplyState.block));\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, supplyTokens) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: supplyState.index }), ratio);\n supplyState.index = safe224(index.mantissa, \"new index overflows\");\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/ApproveOrRevert.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nlibrary ApproveOrRevert {\n /// @notice Thrown if a contract is unable to approve a transfer\n error ApproveFailed();\n\n /// @notice Approves a transfer, ensuring that it is successful. This function supports non-compliant\n /// tokens like the ones that don't return a boolean value on success. Thus, such approve call supports\n /// three different kinds of tokens:\n /// * Compliant tokens that revert on failure\n /// * Compliant tokens that return false on failure\n /// * Non-compliant tokens that don't return a value\n /// @param token The contract address of the token which will be transferred\n /// @param spender The spender contract address\n /// @param amount The value of the transfer\n function approveOrRevert(\n IERC20Upgradeable token,\n address spender,\n uint256 amount\n ) internal {\n bytes memory callData = abi.encodeCall(token.approve, (spender, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory result) = address(token).call(callData);\n\n if (!success || (result.length != 0 && !abi.decode(result, (bool)))) {\n revert ApproveFailed();\n }\n }\n}\n" + }, + "contracts/lib/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" + }, + "contracts/lib/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/lib/TokenDebtTracker.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n/**\n * @title TokenDebtTracker\n * @author Venus\n * @notice TokenDebtTracker is an abstract contract that handles transfers _out_ of the inheriting contract.\n * If there is an error transferring out (due to any reason, e.g. the token contract restricted the user from\n * receiving incoming transfers), the amount is recorded as a debt that can be claimed later.\n * @dev Note that the inheriting contract keeps some amount of users' tokens on its balance, so be careful when\n * using balanceOf(address(this))!\n */\nabstract contract TokenDebtTracker is Initializable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => (address user => uint256 amount)).\n * Tracks failed transfers: when a token transfer fails, we record the\n * amount of the transfer, so that the user can redeem this debt later.\n */\n mapping(IERC20Upgradeable => mapping(address => uint256)) public tokenDebt;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => uint256 amount) shows how many\n * tokens the contract owes to all users. This is useful for accounting to\n * understand how much of balanceOf(address(this)) is already owed to users.\n */\n mapping(IERC20Upgradeable => uint256) public totalTokenDebt;\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[48] private __gap;\n\n /**\n * @notice Emitted when the contract's debt to the user is increased due to a failed transfer\n * @param token Token address\n * @param user User address\n * @param amount The amount of debt added\n */\n event TokenDebtAdded(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Emitted when a user claims tokens that the contract owes them\n * @param token Token address\n * @param user User address\n * @param amount The amount transferred\n */\n event TokenDebtClaimed(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Thrown if the user tries to claim more tokens than they are owed\n * @param token The token the user is trying to claim\n * @param owedAmount The amount of tokens the contract owes to the user\n * @param amount The amount of tokens the user is trying to claim\n */\n error InsufficientDebt(address token, address user, uint256 owedAmount, uint256 amount);\n\n /**\n * @notice Thrown if trying to transfer more tokens than the contract currently has\n * @param token The token the contract is trying to transfer\n * @param recipient The recipient of the transfer\n * @param amount The amount of tokens the contract is trying to transfer\n * @param availableBalance The amount of tokens the contract currently has\n */\n error InsufficientBalance(address token, address recipient, uint256 amount, uint256 availableBalance);\n\n /**\n * @notice Transfers the tokens we owe to msg.sender, if any\n * @param token The token to claim\n * @param amount_ The amount of tokens to claim (or max uint256 to claim all)\n * @custom:error InsufficientDebt The contract doesn't have enough debt to the user\n */\n function claimTokenDebt(IERC20Upgradeable token, uint256 amount_) external {\n uint256 owedAmount = tokenDebt[token][msg.sender];\n uint256 amount = (amount_ == type(uint256).max ? owedAmount : amount_);\n if (amount > owedAmount) {\n revert InsufficientDebt(address(token), msg.sender, owedAmount, amount);\n }\n unchecked {\n // Safe because we revert if amount > owedAmount above\n tokenDebt[token][msg.sender] = owedAmount - amount;\n }\n totalTokenDebt[token] -= amount;\n emit TokenDebtClaimed(address(token), msg.sender, amount);\n token.safeTransfer(msg.sender, amount);\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function __TokenDebtTracker_init() internal onlyInitializing {\n __TokenDebtTracker_init_unchained();\n }\n\n // solhint-disable-next-line func-name-mixedcase, no-empty-blocks\n function __TokenDebtTracker_init_unchained() internal onlyInitializing {}\n\n /**\n * @dev Transfers tokens to the recipient if the contract has enough balance, or\n * records the debt if the transfer fails due to reasons unrelated to the contract's\n * balance (e.g. if the token forbids transfers to the recipient).\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @custom:error InsufficientBalance The contract doesn't have enough balance to transfer\n */\n function _transferOutOrTrackDebt(\n IERC20Upgradeable token,\n address to,\n uint256 amount\n ) internal {\n uint256 balance = token.balanceOf(address(this));\n if (balance < amount) {\n revert InsufficientBalance(address(token), address(this), amount, balance);\n }\n _transferOutOrTrackDebtSkippingBalanceCheck(token, to, amount);\n }\n\n /**\n * @dev Transfers tokens to the recipient, or records the debt if the transfer fails\n * due to any reason, including insufficient balance.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n */\n function _transferOutOrTrackDebtSkippingBalanceCheck(\n IERC20Upgradeable token,\n address to,\n uint256 amount\n ) internal {\n // We can't use safeTransfer here because we can't try-catch internal calls\n bool success = _tryTransferOut(token, to, amount);\n if (!success) {\n tokenDebt[token][to] += amount;\n totalTokenDebt[token] += amount;\n emit TokenDebtAdded(address(token), to, amount);\n }\n }\n\n /**\n * @dev Either transfers tokens to the recepient or returns false. Supports tokens\n * thet revert or return false to indicate failure, and the non-compliant ones\n * that do not return any value.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @return true if the transfer succeeded, false otherwise\n */\n function _tryTransferOut(\n IERC20Upgradeable token,\n address to,\n uint256 amount\n ) private returns (bool) {\n bytes memory callData = abi.encodeCall(token.transfer, (to, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = address(token).call(callData);\n return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n }\n}\n" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\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\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\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 /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.approve(vTokenAddress, 0);\n underlying.approve(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(\n IERC20Upgradeable token,\n address from,\n uint256 amount\n ) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title PoolRegistryInterface\n * @author Venus\n * @notice Interface implemented by `PoolRegistry`.\n */\ninterface PoolRegistryInterface {\n /**\n * @notice Struct for a Venus interest rate pool.\n */\n struct VenusPool {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n }\n\n /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each block for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller private comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n function initializeMarket(address vToken) external onlyComptroller {\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlock(address[],uint32[],uint32[])\");\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumber();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\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 */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumber = getBlockNumber();\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumber;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n function getBlockNumber() public view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumber();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(\n VToken vToken,\n uint256 supplySpeed,\n uint256 borrowSpeed\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\n * @param vToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n uint256 supplyIndex = supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n uint256 borrowIndex = borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\n\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n supplyState.index = safe224(\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n supplyState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n supplyState.block = blockNumber;\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n borrowState.index = safe224(\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n borrowState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n borrowState.block = blockNumber;\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n}\n" + }, + "contracts/RiskFund/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title IProtocolShareReserve\n * @author Venus\n * @notice Interface implemented by `ProtocolShareReserve`.\n */\ninterface IProtocolShareReserve {\n function updateAssetsState(address comptroller, address asset) external;\n}\n" + }, + "contracts/RiskFund/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 swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external returns (uint256);\n\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updateAssetsState(address comptroller, address asset) external;\n\n function convertibleBaseAsset() external view returns (address);\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n" + }, + "contracts/RiskFund/ProtocolShareReserve.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 { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\nimport { IProtocolShareReserve } from \"./IProtocolShareReserve.sol\";\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { ReserveHelpers } from \"./ReserveHelpers.sol\";\nimport { IRiskFund } from \"./IRiskFund.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\ncontract ProtocolShareReserve is ExponentialNoError, ReserveHelpers, IProtocolShareReserve {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n address public protocolIncome;\n address public riskFund;\n // Percentage of funds not sent to the RiskFund contract when the funds are released, following the project Tokenomics\n uint256 private constant PROTOCOL_SHARE_PERCENTAGE = 50;\n uint256 private constant BASE_UNIT = 100;\n\n /// @notice Emitted when funds are released\n event FundsReleased(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\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 /**\n * @notice Initializes the deployer to owner.\n * @param protocolIncome_ The address protocol income will be sent to\n * @param riskFund_ Risk fund address\n * @custom:error ZeroAddressNotAllowed is thrown when protocol income address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when risk fund address is zero\n */\n function initialize(address protocolIncome_, address riskFund_) external initializer {\n ensureNonzeroAddress(protocolIncome_);\n ensureNonzeroAddress(riskFund_);\n\n __Ownable2Step_init();\n\n protocolIncome = protocolIncome_;\n riskFund = riskFund_;\n }\n\n /**\n * @notice 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 address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Release funds\n * @param comptroller Pool's Comptroller\n * @param asset Asset to be released\n * @param amount Amount to release\n * @return Number of total released tokens\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function releaseFunds(\n address comptroller,\n address asset,\n uint256 amount\n ) external nonReentrant returns (uint256) {\n ensureNonzeroAddress(asset);\n require(amount <= _poolsAssetsReserves[comptroller][asset], \"ProtocolShareReserve: Insufficient pool balance\");\n\n assetsReserves[asset] -= amount;\n _poolsAssetsReserves[comptroller][asset] -= amount;\n uint256 protocolIncomeAmount = mul_(\n Exp({ mantissa: amount }),\n div_(Exp({ mantissa: PROTOCOL_SHARE_PERCENTAGE * EXP_SCALE }), BASE_UNIT)\n ).mantissa;\n\n address riskFund_ = riskFund;\n\n emit FundsReleased(comptroller, asset, amount);\n\n IERC20Upgradeable(asset).safeTransfer(protocolIncome, protocolIncomeAmount);\n IERC20Upgradeable(asset).safeTransfer(riskFund_, amount - protocolIncomeAmount);\n\n // Update the pool asset's state in the risk fund for the above transfer.\n IRiskFund(riskFund_).updateAssetsState(comptroller, asset);\n\n return amount;\n }\n\n /**\n * @notice 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 */\n function updateAssetsState(address comptroller, address asset)\n public\n override(IProtocolShareReserve, ReserveHelpers)\n {\n super.updateAssetsState(comptroller, asset);\n }\n}\n" + }, + "contracts/RiskFund/ReserveHelpers.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\n\ncontract ReserveHelpers is Ownable2StepUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 private constant NOT_ENTERED = 1;\n\n uint256 private constant ENTERED = 2;\n\n // Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools).\n mapping(address => uint256) public assetsReserves;\n\n // Store the asset's reserve per pool in the ProtocolShareReserve.\n // Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal _poolsAssetsReserves;\n\n // Address of pool registry contract\n address public poolRegistry;\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n uint256 internal status;\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 */\n uint256[46] private __gap;\n\n /// @notice Event emitted after the update of the assets reserves.\n /// @param comptroller Pool's Comptroller address\n /// @param asset Token address\n /// @param amount An amount by which the reserves have increased\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice event emitted on sweep token success\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(status != ENTERED, \"re-entered\");\n status = ENTERED;\n _;\n status = NOT_ENTERED;\n }\n\n /**\n * @notice A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input\n * @param _token The address of the BEP-20 token to sweep\n * @param _to Recipient of the output tokens.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n * @custom:access Only Owner\n */\n function sweepToken(address _token, address _to) external onlyOwner nonReentrant {\n ensureNonzeroAddress(_to);\n uint256 balanceDfference_;\n uint256 balance_ = IERC20Upgradeable(_token).balanceOf(address(this));\n\n require(balance_ > assetsReserves[_token], \"ReserveHelpers: Zero surplus tokens\");\n unchecked {\n balanceDfference_ = balance_ - assetsReserves[_token];\n }\n\n emit SweepToken(_token, _to, balanceDfference_);\n IERC20Upgradeable(_token).safeTransfer(_to, balanceDfference_);\n }\n\n /**\n * @notice 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 Asset's reserve in risk fund.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256) {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][asset];\n }\n\n /**\n * @notice 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 * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function updateAssetsState(address comptroller, address asset) public virtual {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n address poolRegistry_ = poolRegistry;\n require(poolRegistry_ != address(0), \"ReserveHelpers: Pool Registry address is not set\");\n require(\n PoolRegistryInterface(poolRegistry_).getVTokenForAsset(comptroller, asset) != address(0),\n \"ReserveHelpers: The pool doesn't support the asset\"\n );\n\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n assetsReserves[asset] += balanceDifference;\n _poolsAssetsReserves[comptroller][asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference);\n }\n }\n}\n" + }, + "contracts/RiskFund/RiskFund.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 { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { IRiskFund } from \"./IRiskFund.sol\";\nimport { ReserveHelpers } from \"./ReserveHelpers.sol\";\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { IPancakeswapV2Router } from \"../IPancakeswapV2Router.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { ApproveOrRevert } from \"../lib/ApproveOrRevert.sol\";\n\n/**\n * @title RiskFund\n * @author Venus\n * @notice Contract with basic features to track/hold different assets for different Comptrollers.\n * @dev This contract does not support BNB.\n */\ncontract RiskFund is AccessControlledV8, ExponentialNoError, ReserveHelpers, MaxLoopsLimitHelper, IRiskFund {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using ApproveOrRevert for IERC20Upgradeable;\n\n address public convertibleBaseAsset;\n address public shortfall;\n address public pancakeSwapRouter;\n uint256 public minAmountToConvert;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when shortfall contract address is updated\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\n\n /// @notice Emitted when convertible base asset is updated\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\n\n /// @notice Emitted when PancakeSwap router contract address is updated\n event PancakeSwapRouterUpdated(address indexed oldPancakeSwapRouter, address indexed newPancakeSwapRouter);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Emitted when pools assets are swapped\n event SwappedPoolsAssets(address[] markets, uint256[] amountsOutMin, uint256 totalAmount);\n\n /// @notice Emitted when reserves are transferred for auction\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\n\n /// @dev Note that the contract is upgradeable. Use initialize() or reinitializers\n /// to set the state variables.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner.\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @param minAmountToConvert_ Minimum amount assets must be worth to convert into base asset\n * @param convertibleBaseAsset_ Address of the base asset\n * @param accessControlManager_ Address of the access control contract\n * @param loopsLimit_ Limit for the loops in the contract to avoid DOS\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n */\n function initialize(\n address pancakeSwapRouter_,\n uint256 minAmountToConvert_,\n address convertibleBaseAsset_,\n address accessControlManager_,\n uint256 loopsLimit_\n ) external initializer {\n ensureNonzeroAddress(pancakeSwapRouter_);\n ensureNonzeroAddress(convertibleBaseAsset_);\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n require(loopsLimit_ > 0, \"Risk Fund: Loops limit can not be zero\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n pancakeSwapRouter = pancakeSwapRouter_;\n minAmountToConvert = minAmountToConvert_;\n convertibleBaseAsset = convertibleBaseAsset_;\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice 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 address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Shortfall contract address setter\n * @param shortfallContractAddress_ Address of the auction contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n */\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\n ensureNonzeroAddress(shortfallContractAddress_);\n\n address oldShortfallContractAddress = shortfall;\n shortfall = shortfallContractAddress_;\n emit ShortfallContractUpdated(oldShortfallContractAddress, shortfallContractAddress_);\n }\n\n /**\n * @notice PancakeSwap router address setter\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n */\n function setPancakeSwapRouter(address pancakeSwapRouter_) external onlyOwner {\n ensureNonzeroAddress(pancakeSwapRouter_);\n address oldPancakeSwapRouter = pancakeSwapRouter;\n pancakeSwapRouter = pancakeSwapRouter_;\n emit PancakeSwapRouterUpdated(oldPancakeSwapRouter, pancakeSwapRouter_);\n }\n\n /**\n * @notice Min amount to convert setter\n * @param minAmountToConvert_ Min amount to convert.\n */\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n uint256 oldMinAmountToConvert = minAmountToConvert;\n minAmountToConvert = minAmountToConvert_;\n emit MinAmountToConvertUpdated(oldMinAmountToConvert, minAmountToConvert_);\n }\n\n /**\n * @notice Sets a new convertible base asset\n * @param _convertibleBaseAsset Address for new convertible base asset.\n */\n function setConvertibleBaseAsset(address _convertibleBaseAsset) external {\n _checkAccessAllowed(\"setConvertibleBaseAsset(address)\");\n require(_convertibleBaseAsset != address(0), \"Risk Fund: new convertible base asset address invalid\");\n\n address oldConvertibleBaseAsset = convertibleBaseAsset;\n convertibleBaseAsset = _convertibleBaseAsset;\n\n emit ConvertibleBaseAssetUpdated(oldConvertibleBaseAsset, _convertibleBaseAsset);\n }\n\n /**\n * @notice Swap array of pool assets into base asset's tokens of at least a minimum amount\n * @param markets Array of vTokens whose assets to swap for base asset\n * @param amountsOutMin Minimum amount to receive for swap\n * @param paths A path consisting of PCS token pairs for each swap\n * @param deadline Deadline for the swap\n * @return Number of swapped tokens\n * @custom:error ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\n */\n function swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external override nonReentrant returns (uint256) {\n _checkAccessAllowed(\"swapPoolsAssets(address[],uint256[],address[][],uint256)\");\n require(deadline >= block.timestamp, \"Risk fund: deadline passed\");\n address poolRegistry_ = poolRegistry;\n ensureNonzeroAddress(poolRegistry_);\n require(markets.length == amountsOutMin.length, \"Risk fund: markets and amountsOutMin are unequal lengths\");\n require(markets.length == paths.length, \"Risk fund: markets and paths are unequal lengths\");\n\n uint256 totalAmount;\n uint256 marketsCount = markets.length;\n\n _ensureMaxLoops(marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n address comptroller = address(VToken(markets[i]).comptroller());\n\n PoolRegistry.VenusPool memory pool = PoolRegistry(poolRegistry_).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n require(Comptroller(comptroller).isMarketListed(VToken(markets[i])), \"market is not listed\");\n\n uint256 swappedTokens = _swapAsset(VToken(markets[i]), comptroller, amountsOutMin[i], paths[i]);\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] += swappedTokens;\n assetsReserves[convertibleBaseAsset] += swappedTokens;\n totalAmount = totalAmount + swappedTokens;\n }\n\n emit SwappedPoolsAssets(markets, amountsOutMin, totalAmount);\n\n return totalAmount;\n }\n\n /**\n * @notice Transfer tokens for auction.\n * @param comptroller Comptroller of the pool.\n * @param amount Amount to be transferred to auction contract.\n * @return Number reserved tokens.\n */\n function transferReserveForAuction(address comptroller, uint256 amount)\n external\n override\n nonReentrant\n returns (uint256)\n {\n address shortfall_ = shortfall;\n require(msg.sender == shortfall_, \"Risk fund: Only callable by Shortfall contract\");\n require(\n amount <= _poolsAssetsReserves[comptroller][convertibleBaseAsset],\n \"Risk Fund: Insufficient pool reserve.\"\n );\n unchecked {\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] =\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] -\n amount;\n }\n unchecked {\n assetsReserves[convertibleBaseAsset] = assetsReserves[convertibleBaseAsset] - amount;\n }\n\n emit TransferredReserveForAuction(comptroller, amount);\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall_, amount);\n\n return amount;\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 */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\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 require(ComptrollerInterface(comptroller).isComptroller(), \"Risk Fund: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][convertibleBaseAsset];\n }\n\n /**\n * @notice Update the reserve of the asset for the specific pool after transferring to risk fund.\n * @param comptroller Comptroller address(pool).\n * @param asset Asset address.\n */\n function updateAssetsState(address comptroller, address asset) public override(IRiskFund, ReserveHelpers) {\n super.updateAssetsState(comptroller, asset);\n }\n\n /**\n * @dev Swap single asset to base asset.\n * @param vToken VToken\n * @param comptroller Comptroller address\n * @param amountOutMin Minimum amount to receive for swap\n * @param path A path for the swap consisting of PCS token pairs\n * @return Number of swapped tokens.\n */\n function _swapAsset(\n VToken vToken,\n address comptroller,\n uint256 amountOutMin,\n address[] calldata path\n ) internal returns (uint256) {\n require(amountOutMin != 0, \"RiskFund: amountOutMin must be greater than 0 to swap vToken\");\n uint256 totalAmount;\n\n address underlyingAsset = vToken.underlying();\n address convertibleBaseAsset_ = convertibleBaseAsset;\n uint256 balanceOfUnderlyingAsset = _poolsAssetsReserves[comptroller][underlyingAsset];\n\n if (balanceOfUnderlyingAsset == 0) {\n return 0;\n }\n\n ResilientOracleInterface oracle = ComptrollerViewInterface(comptroller).oracle();\n oracle.updateAssetPrice(convertibleBaseAsset_);\n Exp memory baseAssetPrice = Exp({ mantissa: oracle.getPrice(convertibleBaseAsset_) });\n uint256 amountOutMinInUsd = mul_ScalarTruncate(baseAssetPrice, amountOutMin);\n\n require(amountOutMinInUsd >= minAmountToConvert, \"RiskFund: minAmountToConvert violated\");\n\n assetsReserves[underlyingAsset] -= balanceOfUnderlyingAsset;\n _poolsAssetsReserves[comptroller][underlyingAsset] -= balanceOfUnderlyingAsset;\n\n if (underlyingAsset != convertibleBaseAsset_) {\n require(path[0] == underlyingAsset, \"RiskFund: swap path must start with the underlying asset\");\n require(\n path[path.length - 1] == convertibleBaseAsset_,\n \"RiskFund: finally path must be convertible base asset\"\n );\n address pancakeSwapRouter_ = pancakeSwapRouter;\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, 0);\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, balanceOfUnderlyingAsset);\n uint256[] memory amounts = IPancakeswapV2Router(pancakeSwapRouter_).swapExactTokensForTokens(\n balanceOfUnderlyingAsset,\n amountOutMin,\n path,\n address(this),\n block.timestamp\n );\n totalAmount = amounts[path.length - 1];\n } else {\n totalAmount = balanceOfUnderlyingAsset;\n }\n\n return totalAmount;\n }\n}\n" + }, + "contracts/Shortfall/Shortfall.sol": { + "content": "/// @notice SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { IRiskFund } from \"../RiskFund/IRiskFund.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { TokenDebtTracker } from \"../lib/TokenDebtTracker.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { EXP_SCALE } from \"../lib/constants.sol\";\n\n/**\n * @title Shortfall\n * @author Venus\n * @notice Shortfall is an auction contract designed to auction off the `convertibleBaseAsset` accumulated in `RiskFund`. The `convertibleBaseAsset`\n * is auctioned in exchange for users paying off the pool's bad debt. An auction can be started by anyone once a pool's bad debt has reached a minimum value.\n * This value is set and can be changed by the authorized accounts. If the pool’s bad debt exceeds the risk fund plus a 10% incentive, then the auction winner\n * is determined by who will pay off the largest percentage of the pool's bad debt. The auction winner then exchanges for the entire risk fund. Otherwise,\n * if the risk fund covers the pool's bad debt plus the 10% incentive, then the auction winner is determined by who will take the smallest percentage of the\n * risk fund in exchange for paying off all the pool's bad debt.\n */\ncontract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGuardUpgradeable, TokenDebtTracker {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Type of auction\n enum AuctionType {\n LARGE_POOL_DEBT,\n LARGE_RISK_FUND\n }\n\n /// @notice Status of auction\n enum AuctionStatus {\n NOT_STARTED,\n STARTED,\n ENDED\n }\n\n /// @notice Auction metadata\n struct Auction {\n uint256 startBlock;\n AuctionType auctionType;\n AuctionStatus status;\n VToken[] markets;\n uint256 seizedRiskFund;\n address highestBidder;\n uint256 highestBidBps;\n uint256 highestBidBlock;\n uint256 startBidBps;\n mapping(VToken => uint256) marketDebt;\n mapping(VToken => uint256) bidAmount;\n }\n\n /// @dev Max basis points i.e., 100%\n uint256 private constant MAX_BPS = 10000;\n\n uint256 private constant DEFAULT_NEXT_BIDDER_BLOCK_LIMIT = 100;\n\n uint256 private constant DEFAULT_WAIT_FOR_FIRST_BIDDER = 100;\n\n uint256 private constant DEFAULT_INCENTIVE_BPS = 1000; // 10%\n\n /// @notice Pool registry address\n address public poolRegistry;\n\n /// @notice Risk fund address\n IRiskFund public riskFund;\n\n /// @notice Minimum USD debt in pool for shortfall to trigger\n uint256 public minimumPoolBadDebt;\n\n /// @notice Incentive to auction participants, initial value set to 1000 or 10%\n uint256 public incentiveBps;\n\n /// @notice Time to wait for next bidder. Initially waits for 100 blocks\n uint256 public nextBidderBlockLimit;\n\n /// @notice Boolean of if auctions are paused\n bool public auctionsPaused;\n\n /// @notice Time to wait for first bidder. Initially waits for 100 blocks\n uint256 public waitForFirstBidder;\n\n /// @notice Auctions for each pool\n mapping(address => Auction) public auctions;\n\n /// @notice Emitted when a auction starts\n event AuctionStarted(\n address indexed comptroller,\n uint256 auctionStartBlock,\n AuctionType auctionType,\n VToken[] markets,\n uint256[] marketsDebt,\n uint256 seizedRiskFund,\n uint256 startBidBps\n );\n\n /// @notice Emitted when a bid is placed\n event BidPlaced(address indexed comptroller, uint256 auctionStartBlock, uint256 bidBps, address indexed bidder);\n\n /// @notice Emitted when a auction is completed\n event AuctionClosed(\n address indexed comptroller,\n uint256 auctionStartBlock,\n address indexed highestBidder,\n uint256 highestBidBps,\n uint256 seizedRiskFind,\n VToken[] markets,\n uint256[] marketDebt\n );\n\n /// @notice Emitted when a auction is restarted\n event AuctionRestarted(address indexed comptroller, uint256 auctionStartBlock);\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when minimum pool bad debt is updated\n event MinimumPoolBadDebtUpdated(uint256 oldMinimumPoolBadDebt, uint256 newMinimumPoolBadDebt);\n\n /// @notice Emitted when wait for first bidder block count is updated\n event WaitForFirstBidderUpdated(uint256 oldWaitForFirstBidder, uint256 newWaitForFirstBidder);\n\n /// @notice Emitted when next bidder block limit is updated\n event NextBidderBlockLimitUpdated(uint256 oldNextBidderBlockLimit, uint256 newNextBidderBlockLimit);\n\n /// @notice Emitted when incentiveBps is updated\n event IncentiveBpsUpdated(uint256 oldIncentiveBps, uint256 newIncentiveBps);\n\n /// @notice Emitted when auctions are paused\n event AuctionsPaused(address sender);\n\n /// @notice Emitted when auctions are unpaused\n event AuctionsResumed(address sender);\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 /**\n * @notice Initialize the shortfall contract\n * @param riskFund_ RiskFund contract address\n * @param minimumPoolBadDebt_ Minimum bad debt in base asset for a pool to start auction\n * @param accessControlManager_ AccessControlManager contract address\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when risk fund address is zero\n */\n function initialize(\n IRiskFund riskFund_,\n uint256 minimumPoolBadDebt_,\n address accessControlManager_\n ) external initializer {\n ensureNonzeroAddress(address(riskFund_));\n require(minimumPoolBadDebt_ != 0, \"invalid minimum pool bad debt\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n __ReentrancyGuard_init();\n __TokenDebtTracker_init();\n minimumPoolBadDebt = minimumPoolBadDebt_;\n riskFund = riskFund_;\n waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER;\n nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_LIMIT;\n incentiveBps = DEFAULT_INCENTIVE_BPS;\n auctionsPaused = false;\n }\n\n /**\n * @notice Place a bid greater than the previous in an ongoing auction\n * @param comptroller Comptroller address of the pool\n * @param bidBps The bid percent of the risk fund or bad debt depending on auction type\n * @param auctionStartBlock The block number when auction started\n * @custom:event Emits BidPlaced event on success\n */\n function placeBid(\n address comptroller,\n uint256 bidBps,\n uint256 auctionStartBlock\n ) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(auction.startBlock == auctionStartBlock, \"auction has been restarted\");\n require(_isStarted(auction), \"no on-going auction\");\n require(!_isStale(auction), \"auction is stale, restart it\");\n require(bidBps > 0, \"basis points cannot be zero\");\n require(bidBps <= MAX_BPS, \"basis points cannot be more than 10000\");\n require(\n (auction.auctionType == AuctionType.LARGE_POOL_DEBT &&\n ((auction.highestBidder != address(0) && bidBps > auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps >= auction.startBidBps))) ||\n (auction.auctionType == AuctionType.LARGE_RISK_FUND &&\n ((auction.highestBidder != address(0) && bidBps < auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps <= auction.startBidBps))),\n \"your bid is not the highest\"\n );\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n if (auction.highestBidder != address(0)) {\n _transferOutOrTrackDebt(erc20, auction.highestBidder, auction.bidAmount[auction.markets[i]]);\n }\n uint256 balanceBefore = erc20.balanceOf(address(this));\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n uint256 currentBidAmount = ((auction.marketDebt[auction.markets[i]] * bidBps) / MAX_BPS);\n erc20.safeTransferFrom(msg.sender, address(this), currentBidAmount);\n } else {\n erc20.safeTransferFrom(msg.sender, address(this), auction.marketDebt[auction.markets[i]]);\n }\n\n uint256 balanceAfter = erc20.balanceOf(address(this));\n auction.bidAmount[auction.markets[i]] = balanceAfter - balanceBefore;\n }\n\n auction.highestBidder = msg.sender;\n auction.highestBidBps = bidBps;\n auction.highestBidBlock = block.number;\n\n emit BidPlaced(comptroller, auction.startBlock, bidBps, msg.sender);\n }\n\n /**\n * @notice Close an auction\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionClosed event on successful close\n */\n function closeAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(_isStarted(auction), \"no on-going auction\");\n require(\n block.number > auction.highestBidBlock + nextBidderBlockLimit && auction.highestBidder != address(0),\n \"waiting for next bidder. cannot close auction\"\n );\n\n uint256 marketsCount = auction.markets.length;\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n\n auction.status = AuctionStatus.ENDED;\n\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n uint256 balanceBefore = erc20.balanceOf(address(auction.markets[i]));\n erc20.safeTransfer(address(auction.markets[i]), auction.bidAmount[auction.markets[i]]);\n uint256 balanceAfter = erc20.balanceOf(address(auction.markets[i]));\n marketsDebt[i] = balanceAfter - balanceBefore;\n\n auction.markets[i].badDebtRecovered(marketsDebt[i]);\n }\n\n uint256 riskFundBidAmount;\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n riskFundBidAmount = auction.seizedRiskFund;\n } else {\n riskFundBidAmount = (auction.seizedRiskFund * auction.highestBidBps) / MAX_BPS;\n }\n\n address convertibleBaseAsset = riskFund.convertibleBaseAsset();\n\n uint256 transferredAmount = riskFund.transferReserveForAuction(comptroller, riskFundBidAmount);\n _transferOutOrTrackDebt(IERC20Upgradeable(convertibleBaseAsset), auction.highestBidder, riskFundBidAmount);\n\n emit AuctionClosed(\n comptroller,\n auction.startBlock,\n auction.highestBidder,\n auction.highestBidBps,\n transferredAmount,\n auction.markets,\n marketsDebt\n );\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionStarted event on success\n * @custom:event Errors if auctions are paused\n */\n function startAuction(address comptroller) external nonReentrant {\n require(!auctionsPaused, \"Auctions are paused\");\n _startAuction(comptroller);\n }\n\n /**\n * @notice Restart an auction\n * @param comptroller Address of the pool\n * @custom:event Emits AuctionRestarted event on successful restart\n */\n function restartAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(!auctionsPaused, \"auctions are paused\");\n require(_isStarted(auction), \"no on-going auction\");\n require(_isStale(auction), \"you need to wait for more time for first bidder\");\n\n auction.status = AuctionStatus.ENDED;\n\n emit AuctionRestarted(comptroller, auction.startBlock);\n _startAuction(comptroller);\n }\n\n /**\n * @notice Update next bidder block limit which is used determine when an auction can be closed\n * @param _nextBidderBlockLimit New next bidder block limit\n * @custom:event Emits NextBidderBlockLimitUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateNextBidderBlockLimit(uint256 _nextBidderBlockLimit) external {\n _checkAccessAllowed(\"updateNextBidderBlockLimit(uint256)\");\n require(_nextBidderBlockLimit != 0, \"_nextBidderBlockLimit must not be 0\");\n uint256 oldNextBidderBlockLimit = nextBidderBlockLimit;\n nextBidderBlockLimit = _nextBidderBlockLimit;\n emit NextBidderBlockLimitUpdated(oldNextBidderBlockLimit, _nextBidderBlockLimit);\n }\n\n /**\n * @notice Updates the incentive BPS\n * @param _incentiveBps New incentive BPS\n * @custom:event Emits IncentiveBpsUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateIncentiveBps(uint256 _incentiveBps) external {\n _checkAccessAllowed(\"updateIncentiveBps(uint256)\");\n require(_incentiveBps != 0, \"incentiveBps must not be 0\");\n uint256 oldIncentiveBps = incentiveBps;\n incentiveBps = _incentiveBps;\n emit IncentiveBpsUpdated(oldIncentiveBps, _incentiveBps);\n }\n\n /**\n * @notice Update minimum pool bad debt to start auction\n * @param _minimumPoolBadDebt Minimum bad debt in BUSD for a pool to start auction\n * @custom:event Emits MinimumPoolBadDebtUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateMinimumPoolBadDebt(uint256 _minimumPoolBadDebt) external {\n _checkAccessAllowed(\"updateMinimumPoolBadDebt(uint256)\");\n uint256 oldMinimumPoolBadDebt = minimumPoolBadDebt;\n minimumPoolBadDebt = _minimumPoolBadDebt;\n emit MinimumPoolBadDebtUpdated(oldMinimumPoolBadDebt, _minimumPoolBadDebt);\n }\n\n /**\n * @notice Update wait for first bidder block count. If the first bid is not made within this limit, the auction is closed and needs to be restarted\n * @param _waitForFirstBidder New wait for first bidder block count\n * @custom:event Emits WaitForFirstBidderUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateWaitForFirstBidder(uint256 _waitForFirstBidder) external {\n _checkAccessAllowed(\"updateWaitForFirstBidder(uint256)\");\n uint256 oldWaitForFirstBidder = waitForFirstBidder;\n waitForFirstBidder = _waitForFirstBidder;\n emit WaitForFirstBidderUpdated(oldWaitForFirstBidder, _waitForFirstBidder);\n }\n\n /**\n * @notice Update the pool registry this shortfall supports\n * @dev After Pool Registry is deployed we need to set the pool registry address\n * @param poolRegistry_ Address of pool registry contract\n * @custom:event Emits PoolRegistryUpdated on success\n * @custom:access Restricted to owner\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function updatePoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Pause auctions. This disables starting new auctions but lets the current auction finishes\n * @custom:event Emits AuctionsPaused on success\n * @custom:error Errors is auctions are paused\n * @custom:access Restricted by ACM\n */\n function pauseAuctions() external {\n _checkAccessAllowed(\"pauseAuctions()\");\n require(!auctionsPaused, \"Auctions are already paused\");\n auctionsPaused = true;\n emit AuctionsPaused(msg.sender);\n }\n\n /**\n * @notice Resume paused auctions.\n * @custom:event Emits AuctionsResumed on success\n * @custom:error Errors is auctions are active\n * @custom:access Restricted by ACM\n */\n function resumeAuctions() external {\n _checkAccessAllowed(\"resumeAuctions()\");\n require(auctionsPaused, \"Auctions are not paused\");\n auctionsPaused = false;\n emit AuctionsResumed(msg.sender);\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n */\n function _startAuction(address comptroller) internal {\n PoolRegistryInterface.VenusPool memory pool = PoolRegistry(poolRegistry).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n\n Auction storage auction = auctions[comptroller];\n require(\n auction.status == AuctionStatus.NOT_STARTED || auction.status == AuctionStatus.ENDED,\n \"auction is on-going\"\n );\n\n auction.highestBidBps = 0;\n auction.highestBidBlock = 0;\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = auction.markets[i];\n auction.marketDebt[vToken] = 0;\n }\n\n delete auction.markets;\n\n VToken[] memory vTokens = _getAllMarkets(comptroller);\n marketsCount = vTokens.length;\n ResilientOracleInterface priceOracle = _getPriceOracle(comptroller);\n uint256 poolBadDebt;\n\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n auction.markets = new VToken[](marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n uint256 marketBadDebt = vTokens[i].badDebt();\n\n priceOracle.updatePrice(address(vTokens[i]));\n uint256 usdValue = (priceOracle.getUnderlyingPrice(address(vTokens[i])) * marketBadDebt) / EXP_SCALE;\n\n poolBadDebt = poolBadDebt + usdValue;\n auction.markets[i] = vTokens[i];\n auction.marketDebt[vTokens[i]] = marketBadDebt;\n marketsDebt[i] = marketBadDebt;\n }\n\n require(poolBadDebt >= minimumPoolBadDebt, \"pool bad debt is too low\");\n\n priceOracle.updateAssetPrice(riskFund.convertibleBaseAsset());\n uint256 riskFundBalance = (priceOracle.getPrice(riskFund.convertibleBaseAsset()) *\n riskFund.getPoolsBaseAssetReserves(comptroller)) / EXP_SCALE;\n uint256 remainingRiskFundBalance = riskFundBalance;\n uint256 badDebtPlusIncentive = poolBadDebt + ((poolBadDebt * incentiveBps) / MAX_BPS);\n if (badDebtPlusIncentive >= riskFundBalance) {\n auction.startBidBps =\n (MAX_BPS * MAX_BPS * remainingRiskFundBalance) /\n (poolBadDebt * (MAX_BPS + incentiveBps));\n remainingRiskFundBalance = 0;\n auction.auctionType = AuctionType.LARGE_POOL_DEBT;\n } else {\n uint256 maxSeizeableRiskFundBalance = badDebtPlusIncentive;\n\n remainingRiskFundBalance = remainingRiskFundBalance - maxSeizeableRiskFundBalance;\n auction.auctionType = AuctionType.LARGE_RISK_FUND;\n auction.startBidBps = MAX_BPS;\n }\n\n auction.seizedRiskFund = riskFundBalance - remainingRiskFundBalance;\n auction.startBlock = block.number;\n auction.status = AuctionStatus.STARTED;\n auction.highestBidder = address(0);\n\n emit AuctionStarted(\n comptroller,\n auction.startBlock,\n auction.auctionType,\n auction.markets,\n marketsDebt,\n auction.seizedRiskFund,\n auction.startBidBps\n );\n }\n\n /**\n * @dev Returns the price oracle of the pool\n * @param comptroller Address of the pool's comptroller\n * @return oracle The pool's price oracle\n */\n function _getPriceOracle(address comptroller) internal view returns (ResilientOracleInterface) {\n return ResilientOracleInterface(ComptrollerViewInterface(comptroller).oracle());\n }\n\n /**\n * @dev Returns all markets of the pool\n * @param comptroller Address of the pool's comptroller\n * @return markets The pool's markets as VToken array\n */\n function _getAllMarkets(address comptroller) internal view returns (VToken[] memory) {\n return ComptrollerInterface(comptroller).getAllMarkets();\n }\n\n /**\n * @dev Checks if the auction has started\n * @param auction The auction to query the status for\n * @return True if the auction has started\n */\n function _isStarted(Auction storage auction) internal view returns (bool) {\n return auction.status == AuctionStatus.STARTED;\n }\n\n /**\n * @dev Checks if the auction is stale, i.e. there's no bidder and the auction\n * was started more than waitForFirstBidder blocks ago.\n * @param auction The auction to query the status for\n * @return True if the auction is stale\n */\n function _isStale(Auction storage auction) internal view returns (bool) {\n bool noBidder = auction.highestBidder == address(0);\n return noBidder && (block.number > auction.startBlock + waitForFirstBidder);\n }\n}\n" + }, + "contracts/test/ComptrollerHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\ncontract ComptrollerHarness is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function harnessFastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n}\n\ncontract EchoTypesComptroller {\n function stringy(string memory s) public pure returns (string memory) {\n return s;\n }\n\n function addresses(address a) public pure returns (address) {\n return a;\n }\n\n function booly(bool b) public pure returns (bool) {\n return b;\n }\n\n function listOInts(uint256[] memory u) public pure returns (uint256[] memory) {\n return u;\n }\n\n function reverty() public pure {\n require(false, \"gotcha sucka\");\n }\n}\n" + }, + "contracts/test/ComptrollerScenario.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\n\ncontract ComptrollerScenario is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function fastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n\n function unlist(VToken vToken) public {\n markets[address(vToken)].isListed = false;\n }\n\n function membershipLength(VToken vToken) public view returns (uint256) {\n return accountAssets[address(vToken)].length;\n }\n}\n" + }, + "contracts/test/ERC20.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeMath } from \"./SafeMath.sol\";\n\ninterface ERC20Base {\n event Approval(address indexed owner, address indexed spender, uint256 value);\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n function approve(address spender, uint256 value) external returns (bool);\n\n function totalSupply() external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function balanceOf(address who) external view returns (uint256);\n}\n\nabstract contract ERC20 is ERC20Base {\n function transfer(address to, uint256 value) external virtual returns (bool);\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n ) external virtual returns (bool);\n}\n\nabstract contract ERC20NS is ERC20Base {\n function transfer(address to, uint256 value) external virtual;\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n ) external virtual;\n}\n\n/**\n * @title Standard ERC20 token\n * @dev Implementation of the basic standard token.\n * See https://github.com/ethereum/EIPs/issues/20\n */\ncontract StandardToken is ERC20 {\n using SafeMath for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public override totalSupply;\n mapping(address => mapping(address => uint256)) public override allowance;\n mapping(address => uint256) public override balanceOf;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external virtual override returns (bool) {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external virtual override returns (bool) {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n\n function approve(address _spender, uint256 amount) external virtual override returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\n/**\n * @title Non-Standard ERC20 token\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ncontract NonStandardToken is ERC20NS {\n using SafeMath for uint256;\n\n string public name;\n uint8 public decimals;\n string public symbol;\n uint256 public override totalSupply;\n mapping(address => mapping(address => uint256)) public override allowance;\n mapping(address => uint256) public override balanceOf;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external override {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external override {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n }\n\n function approve(address _spender, uint256 amount) external override returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\ncontract ERC20Harness is StandardToken {\n using SafeMath for uint256;\n // To support testing, we can specify addresses for which transferFrom should fail and return false\n mapping(address => bool) public failTransferFromAddresses;\n\n // To support testing, we allow the contract to always fail `transfer`.\n mapping(address => bool) public failTransferToAddresses;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function transfer(address dst, uint256 amount) external override returns (bool success) {\n // Added for testing purposes\n if (failTransferToAddresses[dst]) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external override returns (bool success) {\n // Added for testing purposes\n if (failTransferFromAddresses[src]) {\n return false;\n }\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n\n function harnessSetFailTransferFromAddress(address src, bool _fail) public {\n failTransferFromAddresses[src] = _fail;\n }\n\n function harnessSetFailTransferToAddress(address dst, bool _fail) public {\n failTransferToAddresses[dst] = _fail;\n }\n\n function harnessSetBalance(address _account, uint256 _amount) public {\n balanceOf[_account] = _amount;\n }\n}\n" + }, + "contracts/test/EvilToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { FaucetToken } from \"./FaucetToken.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title The Compound Evil Test Token\n * @author Compound\n * @notice A simple test token that fails certain operations\n */\ncontract EvilToken is FaucetToken {\n using SafeMath for uint256;\n\n bool public fail;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n fail = true;\n }\n\n function setFail(bool _fail) external {\n fail = _fail;\n }\n\n function transfer(address dst, uint256 amount) external override returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external override returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/FaucetToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { StandardToken, NonStandardToken } from \"./ERC20.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title The Compound Faucet Test Token\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetToken is StandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Compound Faucet Test Token (non-standard)\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetNonStandardToken is NonStandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n NonStandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Compound Faucet Re-Entrant Test Token\n * @author Compound\n * @notice A test token that is malicious and tries to re-enter callers\n */\ncontract FaucetTokenReEntrantHarness {\n using SafeMath for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 private totalSupply_;\n mapping(address => mapping(address => uint256)) private allowance_;\n mapping(address => uint256) private balanceOf_;\n\n bytes public reEntryCallData;\n string public reEntryFun;\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n modifier reEnter(string memory funName) {\n string memory _reEntryFun = reEntryFun;\n if (compareStrings(_reEntryFun, funName)) {\n reEntryFun = \"\"; // Clear re-entry fun\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = msg.sender.call(reEntryCallData);\n // solhint-disable-next-line no-inline-assembly\n assembly {\n if eq(success, 0) {\n revert(add(returndata, 0x20), returndatasize())\n }\n }\n }\n\n _;\n }\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n bytes memory _reEntryCallData,\n string memory _reEntryFun\n ) {\n totalSupply_ = _initialAmount;\n balanceOf_[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n reEntryCallData = _reEntryCallData;\n reEntryFun = _reEntryFun;\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf_[_owner] += value;\n totalSupply_ += value;\n emit Transfer(address(this), _owner, value);\n }\n\n function totalSupply() public reEnter(\"totalSupply\") returns (uint256) {\n return totalSupply_;\n }\n\n function allowance(address owner, address spender) public reEnter(\"allowance\") returns (uint256 remaining) {\n return allowance_[owner][spender];\n }\n\n function approve(address spender, uint256 amount) public reEnter(\"approve\") returns (bool success) {\n _approve(msg.sender, spender, amount);\n return true;\n }\n\n function balanceOf(address owner) public reEnter(\"balanceOf\") returns (uint256 balance) {\n return balanceOf_[owner];\n }\n\n function transfer(address dst, uint256 amount) public reEnter(\"transfer\") returns (bool success) {\n _transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) public reEnter(\"transferFrom\") returns (bool success) {\n _transfer(src, dst, amount);\n _approve(src, msg.sender, allowance_[src][msg.sender].sub(amount));\n return true;\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal {\n require(spender != address(0), \"FaucetToken: approve to the zero address\");\n require(owner != address(0), \"FaucetToken: approve from the zero address\");\n allowance_[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n function _transfer(\n address src,\n address dst,\n uint256 amount\n ) internal {\n require(dst != address(0), \"FaucetToken: transfer to the zero address\");\n balanceOf_[src] = balanceOf_[src].sub(amount);\n balanceOf_[dst] = balanceOf_[dst].add(amount);\n emit Transfer(src, dst, amount);\n }\n\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)));\n }\n}\n" + }, + "contracts/test/FeeToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { FaucetToken } from \"./FaucetToken.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title Fee Token\n * @author Compound\n * @notice A simple test token that charges fees on transfer. Used to mock USDT.\n */\ncontract FeeToken is FaucetToken {\n using SafeMath for uint256;\n\n uint256 public basisPointFee;\n address public owner;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n uint256 _basisPointFee,\n address _owner\n ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n basisPointFee = _basisPointFee;\n owner = _owner;\n }\n\n function transfer(address dst, uint256 amount) public override returns (bool) {\n uint256 fee = amount.mul(basisPointFee).div(10000);\n uint256 net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) public override returns (bool) {\n uint256 fee = amount.mul(basisPointFee).div(10000);\n uint256 net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/HarnessMaxLoopsLimitHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\n\ncontract HarnessMaxLoopsLimitHelper is MaxLoopsLimitHelper {\n function setMaxLoopsLimit(uint256 limit) external {\n _setMaxLoopsLimit(limit);\n }\n\n function ensureMaxLoops(uint256 limit) external view {\n _ensureMaxLoops(limit);\n }\n}\n" + }, + "contracts/test/lib/ApproveOrRevertHarness.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ApproveOrRevert } from \"../../lib/ApproveOrRevert.sol\";\n\ncontract ApproveOrRevertHarness {\n using ApproveOrRevert for IERC20Upgradeable;\n\n function approve(\n IERC20Upgradeable token,\n address spender,\n uint256 amount\n ) external {\n token.approveOrRevert(spender, amount);\n }\n}\n" + }, + "contracts/test/lib/TokenDebtTrackerHarness.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { TokenDebtTracker } from \"../../lib/TokenDebtTracker.sol\";\n\ncontract TokenDebtTrackerHarness is TokenDebtTracker {\n function initialize() external initializer {\n __TokenDebtTracker_init();\n }\n\n function addTokenDebt(\n IERC20Upgradeable token,\n address user,\n uint256 amount\n ) external {\n tokenDebt[token][user] += amount;\n totalTokenDebt[token] += amount;\n }\n\n function transferOutOrTrackDebt(\n IERC20Upgradeable token,\n address user,\n uint256 amount\n ) external {\n _transferOutOrTrackDebt(token, user, amount);\n }\n\n function transferOutOrTrackDebtSkippingBalanceCheck(\n IERC20Upgradeable token,\n address user,\n uint256 amount\n ) external {\n _transferOutOrTrackDebtSkippingBalanceCheck(token, user, amount);\n }\n}\n" + }, + "contracts/test/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 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/MockPriceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { BinanceOracle } from \"@venusprotocol/oracle/contracts/oracles/BinanceOracle.sol\";\nimport { ChainlinkOracle } from \"@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol\";\n\nimport { VToken } from \"../../VToken.sol\";\n\ncontract MockPriceOracle is ResilientOracleInterface {\n mapping(address => uint256) public assetPrices;\n\n //set price in 6 decimal precision\n // solhint-disable-next-line no-empty-blocks\n constructor() {}\n\n function setPrice(address asset, uint256 price) external {\n assetPrices[asset] = price;\n }\n\n // solhint-disable-next-line no-empty-blocks\n function updatePrice(address vToken) external override {}\n\n // solhint-disable-next-line no-empty-blocks\n function updateAssetPrice(address asset) external override {}\n\n function getPrice(address asset) external view returns (uint256) {\n return assetPrices[asset];\n }\n\n //https://compound.finance/docs/prices\n function getUnderlyingPrice(address vToken) public view override returns (uint256) {\n return assetPrices[VToken(vToken).underlying()];\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 decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/test/SafeMath.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\n// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol\n// Subject to the MIT license.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c;\n unchecked {\n c = a + b;\n }\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n uint256 c;\n unchecked {\n c = a + b;\n }\n require(c >= a, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction underflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n */\n function sub(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c;\n unchecked {\n c = a * b;\n }\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c;\n unchecked {\n c = a * b;\n }\n require(c / a == b, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers.\n * Reverts on division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers.\n * Reverts with custom message on division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "contracts/test/UpgradedVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\n/**\n * @title Venus's VToken Contract\n * @notice VTokens which wrap an EIP-20 underlying and are immutable\n * @author Venus\n */\ncontract UpgradedVToken is VToken {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param riskManagement Addresses of risk fund contracts\n */\n\n /// @notice We added this new function to test contract upgrade\n function version() external pure returns (uint256) {\n return 2;\n }\n\n function initializeV2(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) public reinitializer(2) {\n super._initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\n );\n }\n\n function getTokenUnderlying() public view returns (address) {\n return underlying;\n }\n}\n" + }, + "contracts/test/VTokenHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\ncontract VTokenHarness is VToken {\n uint256 public blockNumber;\n uint256 public harnessExchangeRate;\n bool public harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function harnessSetAccrualBlockNumber(uint256 accrualBlockNumber_) external {\n accrualBlockNumber = accrualBlockNumber_;\n }\n\n function harnessSetBlockNumber(uint256 newBlockNumber) external {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint256 blocks) external {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint256 amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetTotalSupply(uint256 totalSupply_) external {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint256 totalBorrows_) external {\n totalBorrows = totalBorrows_;\n }\n\n function harnessSetTotalReserves(uint256 totalReserves_) external {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(\n uint256 totalSupply_,\n uint256 totalBorrows_,\n uint256 totalReserves_\n ) external {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint256 exchangeRate) external {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address to_, bool fail_) external {\n failTransferToAddresses[to_] = fail_;\n }\n\n function harnessMintFresh(address account, uint256 mintAmount) external {\n super._mintFresh(account, account, mintAmount);\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint256 vTokenAmount,\n uint256 underlyingAmount\n ) external {\n super._redeemFresh(account, vTokenAmount, underlyingAmount);\n }\n\n function harnessSetAccountBorrows(\n address account,\n uint256 principal,\n uint256 interestIndex\n ) external {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint256 borrowIndex_) external {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint256 borrowAmount) external {\n _borrowFresh(account, borrowAmount);\n }\n\n function harnessRepayBorrowFresh(\n address payer,\n address account,\n uint256 repayAmount\n ) external {\n _repayBorrowFresh(payer, account, repayAmount);\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VToken vTokenCollateral,\n bool skipLiquidityCheck\n ) external {\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n function harnessReduceReservesFresh(uint256 amount) external {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint256 newReserveFactorMantissa) external {\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) external {\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessAccountBorrows(address account) external view returns (uint256 principal, uint256 interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function getBorrowRateMaxMantissa() external pure returns (uint256) {\n return MAX_BORROW_RATE_MANTISSA;\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModel(newInterestRateModelAddress);\n }\n\n function harnessCallPreBorrowHook(uint256 amount) public {\n comptroller.preBorrowHook(address(this), msg.sender, amount);\n }\n\n function _doTransferOut(address to, uint256 amount) internal override {\n require(failTransferToAddresses[to] == false, \"HARNESS_TOKEN_TRANSFER_OUT_FAILED\");\n return super._doTransferOut(to, amount);\n }\n\n function _exchangeRateStored() internal view override returns (uint256) {\n if (harnessExchangeRateStored) {\n return harnessExchangeRate;\n }\n return super._exchangeRateStored();\n }\n\n function _getBlockNumber() internal view override returns (uint256) {\n return blockNumber;\n }\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { IProtocolShareReserve } from \"./RiskFund/IProtocolShareReserve.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\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 /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\n );\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\n return true;\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\n return totalBorrows;\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\n _redeemFresh(msg.sender, redeemTokens, 0);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\n _redeemFresh(msg.sender, 0, redeemAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n _borrowFresh(msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\n }\n\n /**\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(\n address payer,\n address borrower,\n uint256 repayAmount\n ) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint256) {\n return transferAllowances[owner][spender];\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return amount The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint256) {\n return accountTokens[owner];\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(address account)\n external\n view\n override\n returns (\n uint256 error,\n uint256 vTokenBalance,\n uint256 borrowBalance,\n uint256 exchangeRate\n )\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return rate The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this v\n * @return rate The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\n return _exchangeRateStored();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number */\n uint256 currentBlockNumber = _getBlockNumber();\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return NO_ERROR;\n }\n\n /**\n * @notice User supplies assets into the market and receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param payer The address of the account which is sending the assets for supply\n * @param minter The address of the account which is supplying the assets\n * @param mintAmount The amount of the underlying asset to supply\n */\n function _mintFresh(\n address payer,\n address minter,\n uint256 mintAmount\n ) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `_doTransferIn` for the minter and the mintAmount.\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\n\n /*\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n }\n\n /**\n * @notice User redeems vTokens in exchange for the underlying asset\n * @dev Assumes interest has already been accrued up to the current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n */\n function _redeemFresh(\n address redeemer,\n uint256 redeemTokensIn,\n uint256 redeemAmountIn\n ) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\n\n /* If redeemTokensIn > 0: */\n if (redeemTokensIn > 0) {\n /*\n * We calculate the exchange rate and the amount of underlying to be redeemed:\n * redeemTokens = redeemTokensIn\n */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\n * On success, the vToken has redeemAmount less of cash.\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n _doTransferOut(redeemer, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n }\n\n /**\n * @notice Users borrow assets from the protocol to their own address\n * @param borrower User who borrows the assets\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the borrower and the borrowAmount.\n * On success, the vToken borrowAmount less of cash.\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n _doTransferOut(borrower, borrowAmount);\n\n /* We emit a Borrow event */\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\n }\n\n /**\n * @notice Borrows are repaid by another user (possibly the borrower).\n * @param payer the account paying off the borrow\n * @param borrower the account with the debt being payed off\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(\n address payer,\n address borrower,\n uint256 repayAmount\n ) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call _doTransferIn for the payer and the repayAmount\n * On success, the vToken holds an additional repayAmount of cash.\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\n\n /*\n * We calculate the new borrower and total borrow balances, failing on underflow:\n * accountBorrowsNew = accountBorrows - actualRepayAmount\n * totalBorrowsNew = totalBorrows - actualRepayAmount\n */\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == NO_ERROR, \"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\");\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"LIQUIDATE_SEIZE_TOO_MUCH\");\n\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n */\n function _seize(\n address seizerContract,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\n\n /*\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\n */\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n uint256 totalReservesNew = totalReserves + protocolSeizeAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalReserves = totalReservesNew;\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit Transfer(borrower, address(this), protocolSeizeTokens);\n emit ReservesAdded(address(this), protocolSeizeAmount, totalReservesNew);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\n ComptrollerInterface oldComptroller = comptroller;\n // Ensure invoke comptroller.isComptroller() returns true\n require(newComptroller.isComptroller(), \"marker method returned false\");\n\n // Set market's comptroller to newComptroller\n comptroller = newComptroller;\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(oldComptroller, newComptroller);\n }\n\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n }\n\n /**\n * @notice Add reserves by transferring from caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n totalReservesNew = totalReserves - reduceAmount;\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(address(comptroller), underlying);\n\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert SetInterestRateModelFreshCheck();\n }\n\n // Track the market's current interest rate model\n oldInterestRateModel = interestRateModel;\n\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\n require(newInterestRateModel.isInterestRateModel(), \"marker method returned false\");\n\n // Set the interest rate model to newInterestRateModel\n interestRateModel = newInterestRateModel;\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\n }\n\n /*** Safe Token ***/\n\n /**\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n * @param from Sender of the underlying tokens\n * @param amount Amount of underlying to transfer\n * @return Actual amount received\n */\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n // Return the amount that was *actually* transferred\n return balanceAfter - balanceBefore;\n }\n\n /**\n * @dev Just a regular ERC-20 transfer, reverts on failure\n * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\n * @dev Called by both `transfer` and `transferFrom` internally\n * @param spender The address of the account performing the transfer\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param tokens The number of tokens to transfer\n */\n function _transferTokens(\n address spender,\n address src,\n address dst,\n uint256 tokens\n ) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\n if (spender == src) {\n startingAllowance = type(uint256).max;\n } else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under,over}flow */\n uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if necessary) */\n if (startingAllowance != type(uint256).max) {\n transferAllowances[src][spender] = allowanceNew;\n }\n\n /* We emit a Transfer event */\n emit Transfer(src, dst, tokens);\n }\n\n /**\n * @notice Initialize the money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n require(accrualBlockNumber == 0 && borrowIndex == 0, \"market may only be initialized once\");\n\n // Set initial exchange rate\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa > 0, \"initial exchange rate must be greater than zero.\");\n\n _setComptroller(comptroller_);\n\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\n accrualBlockNumber = _getBlockNumber();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on block number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying tokens owned by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n return token.balanceOf(address(this));\n }\n\n /**\n * @dev Function to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n * @return Current block number\n */\n function _getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\n\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\n */\n if (borrowSnapshot.principal == 0) {\n return 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\n */\n struct BorrowSnapshot {\n uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\n\n /**\n * @notice EIP-20 token name for this token\n */\n string public name;\n\n /**\n * @notice EIP-20 token symbol for this token\n */\n string public symbol;\n\n /**\n * @notice EIP-20 token decimals for this token\n */\n uint8 public decimals;\n\n /**\n * @notice Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\n\n // Maximum borrow rate that can ever be applied (.0005% / block)\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n /**\n * @notice Contract which oversees inter-vToken operations\n */\n ComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\n InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\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\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address indexed admin, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(\n address payer,\n address borrower,\n uint256 repayAmount\n ) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account)\n external\n view\n virtual\n returns (\n uint256,\n uint256,\n uint256,\n uint256\n );\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/WhitePaperInterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { EXP_SCALE, MANTISSA_ONE } from \"./lib/constants.sol\";\n\n/**\n * @title Compound's WhitePaperInterestRateModel Contract\n * @author Compound\n * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper\n */\ncontract WhitePaperInterestRateModel is InterestRateModel {\n /**\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\n */\n uint256 public immutable blocksPerYear;\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public immutable multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public immutable baseRatePerBlock;\n\n event NewInterestParams(uint256 baseRatePerBlock, uint256 multiplierPerBlock);\n\n /**\n * @notice Construct an interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n */\n constructor(\n uint256 blocksPerYear_,\n uint256 baseRatePerYear,\n uint256 multiplierPerYear\n ) {\n require(blocksPerYear_ != 0, \"Invalid blocks per year\");\n baseRatePerBlock = baseRatePerYear / blocksPerYear_;\n multiplierPerBlock = multiplierPerYear / blocksPerYear_;\n blocksPerYear = blocksPerYear_;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock);\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public view override returns (uint256) {\n uint256 ur = utilizationRate(cash, borrows, reserves, badDebt);\n return ((ur * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) public view override returns (uint256) {\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\n uint256 borrowRate = getBorrowRate(cash, borrows, reserves, badDebt);\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\n uint256 incomeToDistribute = borrows * rateToPool;\n uint256 supply = cash + borrows + badDebt - reserves;\n return incomeToDistribute / supply;\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @param badDebt The amount of badDebt in the market\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\n */\n function utilizationRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows and badDebt\n if ((borrows + badDebt) == 0) {\n return 0;\n }\n\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\n\n if (rate > EXP_SCALE) {\n rate = EXP_SCALE;\n }\n\n return rate;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/sepolia/solcInputs/cdedc94c3b6a3494ec3d604a8209c227.json b/deployments/sepolia/solcInputs/cdedc94c3b6a3494ec3d604a8209c227.json new file mode 100644 index 000000000..aa7a464af --- /dev/null +++ b/deployments/sepolia/solcInputs/cdedc94c3b6a3494ec3d604a8209c227.json @@ -0,0 +1,300 @@ +{ + "language": "Solidity", + "sources": { + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "@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/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.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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/AccessControlManager.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlManager\n * @author Venus\n * @dev This contract is a wrapper of OpenZeppelin AccessControl extending it in a way to standartize access control within Venus Smart Contract Ecosystem.\n * @notice Access control plays a crucial role in the Venus governance model. It is used to restrict functions so that they can only be called from one\n * account or list of accounts (EOA or Contract Accounts).\n *\n * The implementation of `AccessControlManager`(https://github.com/VenusProtocol/governance-contracts/blob/main/contracts/Governance/AccessControlManager.sol)\n * inherits the [Open Zeppelin AccessControl](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/AccessControl.sol)\n * contract as a base for role management logic. There are two role types: admin and granular permissions.\n * \n * ## Granular Roles\n * \n * Granular roles are built by hashing the contract address and its function signature. For example, given contract `Foo` with function `Foo.bar()` which\n * is guarded by ACM, calling `giveRolePermission` for account B do the following:\n * \n * 1. Compute `keccak256(contractFooAddress,functionSignatureBar)`\n * 1. Add the computed role to the roles of account B\n * 1. Account B now can call `ContractFoo.bar()`\n * \n * ## Admin Roles\n * \n * Admin roles allow for an address to call a function signature on any contract guarded by the `AccessControlManager`. This is particularly useful for\n * contracts created by factories.\n * \n * For Admin roles a null address is hashed in place of the contract address (`keccak256(0x0000000000000000000000000000000000000000,functionSignatureBar)`.\n * \n * In the previous example, giving account B the admin role, account B will have permissions to call the `bar()` function on any contract that is guarded by\n * ACM, not only contract A.\n * \n * ## Protocol Integration\n * \n * All restricted functions in Venus Protocol use a hook to ACM in order to check if the caller has the right permission to call the guarded function.\n * `AccessControlledV5` and `AccessControlledV8` abstract contract makes this integration easier. They call ACM's external method\n * `isAllowedToCall(address caller, string functionSig)`. Here is an example of how `setCollateralFactor` function in `Comptroller` is integrated with ACM:\n\n```\n contract Comptroller is [...] AccessControlledV8 {\n [...]\n function setCollateralFactor(VToken vToken, uint256 newCollateralFactorMantissa, uint256 newLiquidationThresholdMantissa) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n [...]\n }\n }\n```\n */\ncontract AccessControlManager is AccessControl, IAccessControlManagerV8 {\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(address contractAddress, string calldata functionSig, address accountToPermit) 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 calldata 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 calldata 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 calldata functionSig\n ) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n return hasRole(role, account);\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/FeedRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface FeedRegistryInterface {\n function latestRoundDataByName(\n string memory base,\n string memory quote\n )\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n function decimalsByName(string memory base, string memory quote) external view returns (uint8);\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/PublicResolverInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\ninterface PublicResolverInterface {\n function addr(bytes32 node) external view returns (address payable);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/SIDRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.13;\n\ninterface SIDRegistryInterface {\n function resolver(bytes32 node) external view returns (address);\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/oracles/BinanceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/SIDRegistryInterface.sol\";\nimport \"../interfaces/FeedRegistryInterface.sol\";\nimport \"../interfaces/PublicResolverInterface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport \"../interfaces/OracleInterface.sol\";\n\n/**\n * @title BinanceOracle\n * @author Venus\n * @notice This oracle fetches price of assets from Binance.\n */\ncontract BinanceOracle is AccessControlledV8, OracleInterface {\n address public sidRegistryAddress;\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Max stale period configuration for assets\n mapping(string => uint256) public maxStalePeriod;\n\n /// @notice Override symbols to be compatible with Binance feed registry\n mapping(string => string) public symbols;\n\n event MaxStalePeriodAdded(string indexed asset, uint256 maxStalePeriod);\n\n event SymbolOverridden(string indexed symbol, string overriddenSymbol);\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 /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Used to set the max stale period of an asset\n * @param symbol The symbol of the asset\n * @param _maxStalePeriod The max stake period\n */\n function setMaxStalePeriod(string memory symbol, uint256 _maxStalePeriod) external {\n _checkAccessAllowed(\"setMaxStalePeriod(string,uint256)\");\n if (_maxStalePeriod == 0) revert(\"stale period can't be zero\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n maxStalePeriod[symbol] = _maxStalePeriod;\n emit MaxStalePeriodAdded(symbol, _maxStalePeriod);\n }\n\n /**\n * @notice Used to override a symbol when fetching price\n * @param symbol The symbol to override\n * @param overrideSymbol The symbol after override\n */\n function setSymbolOverride(string calldata symbol, string calldata overrideSymbol) external {\n _checkAccessAllowed(\"setSymbolOverride(string,string)\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n symbols[symbol] = overrideSymbol;\n emit SymbolOverridden(symbol, overrideSymbol);\n }\n\n /**\n * @notice Sets the contracts required to fetch prices\n * @param _sidRegistryAddress Address of SID registry\n * @param _accessControlManager Address of the access control manager contract\n */\n function initialize(\n address _sidRegistryAddress,\n address _accessControlManager\n ) external initializer notNullAddress(_sidRegistryAddress) {\n sidRegistryAddress = _sidRegistryAddress;\n __AccessControlled_init(_accessControlManager);\n }\n\n /**\n * @notice Uses Space ID to fetch the feed registry address\n * @return feedRegistryAddress Address of binance oracle feed registry.\n */\n function getFeedRegistryAddress() public view returns (address) {\n bytes32 nodeHash = 0x94fe3821e0768eb35012484db4df61890f9a6ca5bfa984ef8ff717e73139faff;\n\n SIDRegistryInterface sidRegistry = SIDRegistryInterface(sidRegistryAddress);\n address publicResolverAddress = sidRegistry.resolver(nodeHash);\n PublicResolverInterface publicResolver = PublicResolverInterface(publicResolverAddress);\n\n return publicResolver.addr(nodeHash);\n }\n\n /**\n * @notice Gets the price of a asset from the binance oracle\n * @param asset Address of the asset\n * @return Price in USD\n */\n function getPrice(address asset) public view returns (uint256) {\n string memory symbol;\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n symbol = \"BNB\";\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n symbol = token.symbol();\n decimals = token.decimals();\n }\n\n string memory overrideSymbol = symbols[symbol];\n\n if (bytes(overrideSymbol).length != 0) {\n symbol = overrideSymbol;\n }\n\n return _getPrice(symbol, decimals);\n }\n\n function _getPrice(string memory symbol, uint256 decimals) internal view returns (uint256) {\n FeedRegistryInterface feedRegistry = FeedRegistryInterface(getFeedRegistryAddress());\n\n (, int256 answer, , uint256 updatedAt, ) = feedRegistry.latestRoundDataByName(symbol, \"USD\");\n if (answer <= 0) revert(\"invalid binance oracle price\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n if (deltaTime > maxStalePeriod[symbol]) revert(\"binance oracle price expired\");\n\n uint256 decimalDelta = feedRegistry.decimalsByName(symbol, \"USD\");\n return (uint256(answer) * (10 ** (18 - decimalDelta))) * (10 ** (18 - decimals));\n }\n}\n" + }, + "@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ChainlinkOracle\n * @author Venus\n * @notice This oracle fetches prices of assets from the Chainlink oracle.\n */\ncontract ChainlinkOracle is AccessControlledV8, OracleInterface {\n struct TokenConfig {\n /// @notice Underlying token address, which can't be a null address\n /// @notice Used to check if a token is supported\n /// @notice 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB for BNB\n address asset;\n /// @notice Chainlink feed address\n address feed;\n /// @notice Price expiration period of this asset\n uint256 maxStalePeriod;\n }\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Manually set an override price, useful under extenuating conditions such as price feed failure\n mapping(address => uint256) public prices;\n\n /// @notice Token config by assets\n mapping(address => TokenConfig) public tokenConfigs;\n\n /// @notice Emit when a price is manually set\n event PricePosted(address indexed asset, uint256 previousPriceMantissa, uint256 newPriceMantissa);\n\n /// @notice Emit when a token config is added\n event TokenConfigAdded(address indexed asset, address feed, uint256 maxStalePeriod);\n\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Manually set the price of a given asset\n * @param asset Asset address\n * @param price Asset price in 18 decimals\n * @custom:access Only Governance\n * @custom:event Emits PricePosted event on succesfully setup of asset price\n */\n function setDirectPrice(address asset, uint256 price) external notNullAddress(asset) {\n _checkAccessAllowed(\"setDirectPrice(address,uint256)\");\n\n uint256 previousPriceMantissa = prices[asset];\n prices[asset] = price;\n emit PricePosted(asset, previousPriceMantissa, price);\n }\n\n /**\n * @notice Add multiple token configs at the same time\n * @param tokenConfigs_ config array\n * @custom:access Only Governance\n * @custom:error Zero length error thrown, if length of the array in parameter 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 Initializes the owner of the contract\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n }\n\n /**\n * @notice Add single token config. asset & feed cannot be null addresses and maxStalePeriod must be positive\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error NotNullAddress error is thrown if token feed address is null\n * @custom:error Range error is thrown if maxStale period of token is not greater than zero\n * @custom:event Emits TokenConfigAdded event on succesfully setting of the token config\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.feed) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n if (tokenConfig.maxStalePeriod == 0) revert(\"stale period can't be zero\");\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(tokenConfig.asset, tokenConfig.feed, tokenConfig.maxStalePeriod);\n }\n\n /**\n * @notice Gets the price of a asset from the chainlink oracle\n * @param asset Address of the asset\n * @return Price in USD from Chainlink or a manually set price for the asset\n */\n function getPrice(address asset) public view returns (uint256) {\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n decimals = token.decimals();\n }\n\n return _getPriceInternal(asset, decimals);\n }\n\n /**\n * @notice Gets the Chainlink price for a given asset\n * @param asset address of the asset\n * @param decimals decimals of the asset\n * @return price Asset price in USD or a manually set price of the asset\n */\n function _getPriceInternal(address asset, uint256 decimals) internal view returns (uint256 price) {\n uint256 tokenPrice = prices[asset];\n if (tokenPrice != 0) {\n price = tokenPrice;\n } else {\n price = _getChainlinkPrice(asset);\n }\n\n uint256 decimalDelta = 18 - decimals;\n return price * (10 ** decimalDelta);\n }\n\n /**\n * @notice Get the Chainlink price for an asset, revert if token config doesn't exist\n * @dev The precision of the price feed is used to ensure the returned price has 18 decimals of precision\n * @param asset Address of the asset\n * @return price Price in USD, with 18 decimals of precision\n * @custom:error NotNullAddress error is thrown if the asset address is null\n * @custom:error Price error is thrown if the Chainlink price of asset is not greater than zero\n * @custom:error Timing error is thrown if current timestamp is less than the last updatedAt timestamp\n * @custom:error Timing error is thrown if time difference between current time and last updated time\n * is greater than maxStalePeriod\n */\n function _getChainlinkPrice(\n address asset\n ) private view notNullAddress(tokenConfigs[asset].asset) returns (uint256) {\n TokenConfig memory tokenConfig = tokenConfigs[asset];\n AggregatorV3Interface feed = AggregatorV3Interface(tokenConfig.feed);\n\n // note: maxStalePeriod cannot be 0\n uint256 maxStalePeriod = tokenConfig.maxStalePeriod;\n\n // Chainlink USD-denominated feeds store answers at 8 decimals, mostly\n uint256 decimalDelta = 18 - feed.decimals();\n\n (, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData();\n if (answer <= 0) revert(\"chainlink price must be positive\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n\n if (deltaTime > maxStalePeriod) revert(\"chainlink price expired\");\n\n return uint256(answer) * (10 ** decimalDelta);\n }\n}\n" + }, + "@venusprotocol/protocol-reserve/contracts/Interfaces/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface ComptrollerInterface {\n function isComptroller() external view returns (bool);\n}\n" + }, + "@venusprotocol/protocol-reserve/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" + }, + "@venusprotocol/protocol-reserve/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" + }, + "@venusprotocol/protocol-reserve/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" + }, + "@venusprotocol/protocol-reserve/contracts/Interfaces/PoolRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface PoolRegistryInterface {\n /*** get VToken in the Pool for an Asset ***/\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n}\n" + }, + "@venusprotocol/protocol-reserve/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\";\n\nimport { IProtocolShareReserve } from \"../Interfaces/IProtocolShareReserve.sol\";\nimport { ComptrollerInterface } from \"../Interfaces/ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Interfaces/PoolRegistryInterface.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 uint8 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 uint8 public constant MAX_PERCENT = 100;\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 the updation 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 uint8 oldPercentage,\n uint8 newPercentage,\n Schema schema\n );\n\n /// @notice Event emitted when distribution configuration is added\n event DistributionConfigAdded(address indexed destination, uint8 percentage, Schema schema);\n\n /// @notice Event emitted when distribution configuration is removed\n event DistributionConfigRemoved(address indexed destination, uint8 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 if (_corePoolComptroller == address(0)) revert InvalidAddress();\n if (_wbnb == address(0)) revert InvalidAddress();\n if (_vbnb == address(0)) revert InvalidAddress();\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 */\n function setPoolRegistry(address _poolRegistry) external onlyOwner {\n if (_poolRegistry == address(0)) revert InvalidAddress();\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 if (_config.destination == address(0)) revert InvalidAddress();\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 (!ComptrollerInterface(comptroller).isComptroller()) revert InvalidAddress();\n if (asset == address(0)) revert InvalidAddress();\n if (\n comptroller != CORE_POOL_COMPTROLLER &&\n PoolRegistryInterface(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 uint8[] memory totalPercentages = new uint8[](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" + }, + "@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" + }, + "contracts/BaseJumpRateModelV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { EXP_SCALE, MANTISSA_ONE } from \"./lib/constants.sol\";\n\n/**\n * @title Logic for Compound's JumpRateModel Contract V2.\n * @author Compound (modified by Dharma Labs, Arr00 and Venus)\n * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached.\n * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters.\n */\nabstract contract BaseJumpRateModelV2 is InterestRateModel {\n /**\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\n */\n uint256 public immutable blocksPerYear;\n /**\n * @notice The address of the AccessControlManager contract\n */\n IAccessControlManagerV8 public accessControlManager;\n\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public baseRatePerBlock;\n\n /**\n * @notice The multiplier per block after hitting a specified utilization point\n */\n uint256 public jumpMultiplierPerBlock;\n\n /**\n * @notice The utilization point at which the jump multiplier is applied\n */\n uint256 public kink;\n\n event NewInterestParams(\n uint256 baseRatePerBlock,\n uint256 multiplierPerBlock,\n uint256 jumpMultiplierPerBlock,\n uint256 kink\n );\n\n /**\n * @notice Thrown when the action is prohibited by AccessControlManager\n */\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n /**\n * @notice Construct an interest rate model\n * @param blocksPerYear_ The approximate number of blocks per year that is assumed by the interest rate model.\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n * @param accessControlManager_ The address of the AccessControlManager contract\n */\n constructor(\n uint256 blocksPerYear_,\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_,\n IAccessControlManagerV8 accessControlManager_\n ) {\n require(address(accessControlManager_) != address(0), \"invalid ACM address\");\n require(blocksPerYear_ != 0, \"Invalid blocks per year\");\n accessControlManager = accessControlManager_;\n blocksPerYear = blocksPerYear_;\n\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\n }\n\n /**\n * @notice Update the parameters of the interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n * @custom:error Unauthorized if the sender is not allowed to call this function\n * @custom:access Controlled by AccessControlManager\n */\n function updateJumpRateModel(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_\n ) external virtual {\n string memory signature = \"updateJumpRateModel(uint256,uint256,uint256,uint256)\";\n bool isAllowedToCall = accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n\n _updateJumpRateModel(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_);\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) public view virtual override returns (uint256) {\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves, badDebt);\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\n uint256 incomeToDistribute = borrows * rateToPool;\n uint256 supply = cash + borrows + badDebt - reserves;\n return incomeToDistribute / supply;\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @param badDebt The amount of badDebt in the market\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\n */\n function utilizationRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows and badDebt\n if ((borrows + badDebt) == 0) {\n return 0;\n }\n\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\n\n if (rate > EXP_SCALE) {\n rate = EXP_SCALE;\n }\n\n return rate;\n }\n\n /**\n * @notice Internal function to update the parameters of the interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n */\n function _updateJumpRateModel(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_\n ) internal {\n baseRatePerBlock = baseRatePerYear / blocksPerYear;\n multiplierPerBlock = multiplierPerYear / blocksPerYear;\n jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear;\n kink = kink_;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function _getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) internal view returns (uint256) {\n uint256 util = utilizationRate(cash, borrows, reserves, badDebt);\n uint256 kink_ = kink;\n\n if (util <= kink_) {\n return ((util * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n }\n uint256 normalRate = ((kink_ * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n uint256 excessUtil;\n unchecked {\n excessUtil = util - kink_;\n }\n return ((excessUtil * jumpMultiplierPerBlock) / EXP_SCALE) + normalRate;\n }\n}\n" + }, + "contracts/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\n\n /// @notice Emitted when a collateral factor is changed by admin\n event NewCollateralFactor(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\n );\n\n /// @notice Emitted when liquidation incentive is changed by admin\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\n\n /// @notice Emitted when borrow cap for a vToken is changed\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\n\n /// @notice Emitted when the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\n\n /// @notice Emitted when supply cap for a vToken is changed\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\n\n /// @notice Emitted when a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow.\n * @param vTokenAddress The address of the asset to be removed\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\n\n Market storage marketToExit = markets[address(vToken)];\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return NO_ERROR;\n }\n\n /* Set vToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete vToken from the account’s list of assets */\n // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\n\n /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param vToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param vToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param vToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param vToken The market to verify the repay against\n * @param borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if it is a forced liquidation */\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\n }\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param vToken The market to verify the transfer against\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\n _checkActionPauseState(vToken, Action.TRANSFER);\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = accountAssets[user];\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = accountAssets[borrower];\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\n // Set liquidation incentive to new incentive\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n // Emit event with old incentive, new incentive\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"setMarketBorrowCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \"invalid input\");\n\n _ensureMaxLoops(numMarkets);\n\n for (uint256 i; i < numMarkets; ++i) {\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\n }\n }\n\n /**\n * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Enables forced liquidations for a market. If forced liquidation is enabled,\n * borrows in the market may be liquidated regardless of the account liquidity\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n _checkAccessAllowed(\"setForcedLiquidation(address,bool)\");\n ensureNonzeroAddress(vTokenBorrowed);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(vTokenBorrowed);\n }\n\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall Hypothetical account shortfall below collateral requirements\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market.\n * @return markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\n }\n\n /**\n * @notice Check if a market is marked as listed (active)\n * @param vToken vToken Address for the market to check\n * @return listed True if listed otherwise false\n */\n function isMarketListed(VToken vToken) external view returns (bool) {\n return markets[address(vToken)].isListed;\n }\n\n /*** Assets You Are In ***/\n\n /**\n * @notice Returns the assets an account has entered\n * @param account The address of the account to pull assets for\n * @return A list with the assets the account has entered\n */\n function getAssetsIn(address account) external view returns (VToken[] memory) {\n VToken[] memory assetsIn = accountAssets[account];\n\n return assetsIn;\n }\n\n /**\n * @notice Returns whether the given account is entered in a given market\n * @param account The address of the account to check\n * @param vToken The vToken to check\n * @return True if the account is in the market specified, otherwise false.\n */\n function checkMembership(address account, VToken vToken) external view returns (bool) {\n return markets[address(vToken)].accountMembership[account];\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = accountAssets[account];\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param vToken The market to enter\n * @param borrower The address of the account to modify\n */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\n\n // survived the gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n accountAssets[borrower].push(vToken);\n\n emit MarketEntered(vToken, borrower);\n }\n\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\n }\n\n /**\n * @dev Pause/unpause an action on a market\n * @param market Market to pause/unpause the action on\n * @param action Action id to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n */\n function _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = accountAssets[account];\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\n\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // Multiplier representing the most one can borrow against their collateral in this market.\n // For instance, 0.9 to allow borrowing 90% of collateral value.\n // Must be between 0 and 1, and stored as a mantissa.\n uint256 collateralFactorMantissa;\n // Multiplier representing the collateralization after which the borrow is eligible\n // for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\n // value. Must be between 0 and collateral factor, stored as a mantissa.\n uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\n enum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n }\n\n /**\n * @notice Oracle which gives the price of any given asset\n */\n ResilientOracleInterface public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\n uint256 public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives\n */\n uint256 public liquidationIncentiveMantissa;\n\n /**\n * @notice Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\n\n /**\n * @notice Official mapping of vTokens -> Market metadata\n * @dev Used e.g. to determine if a market is supported\n */\n mapping(address => Market) public markets;\n\n /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n /// @notice Flag indicating whether forced liquidation enabled for a market\n mapping(address => bool) public isForcedLiquidationEnabled;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\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" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Compound\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract ExponentialNoError {\n struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return truncate(product);\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return add_(truncate(product), addend);\n }\n\n /**\n * @dev Checks if first Exp is less than second Exp.\n */\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa < right.mantissa;\n }\n\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, errorMessage);\n return uint32(n);\n }\n\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\n }\n\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), b.mantissa);\n }\n\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/IPancakeswapV2Router.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\ninterface IPancakeswapV2Router {\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n}\n" + }, + "contracts/JumpRateModelV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { BaseJumpRateModelV2 } from \"./BaseJumpRateModelV2.sol\";\n\n/**\n * @title Compound's JumpRateModel Contract V2 for V2 vTokens\n * @author Arr00\n * @notice Supports only for V2 vTokens\n */\ncontract JumpRateModelV2 is BaseJumpRateModelV2 {\n constructor(\n uint256 blocksPerYear_,\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_,\n IAccessControlManagerV8 accessControlManager_\n )\n BaseJumpRateModelV2(\n blocksPerYear_,\n baseRatePerYear,\n multiplierPerYear,\n jumpMultiplierPerYear,\n kink_,\n accessControlManager_\n )\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n /**\n * @notice Calculates the current borrow rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view override returns (uint256) {\n return _getBorrowRate(cash, borrows, reserves, badDebt);\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlock;\n uint256 borrowRatePerBlock;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = comptroller.getAllMarkets();\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\n\n return\n VTokenBalances({\n vToken: address(vToken),\n balanceOf: balanceOf,\n borrowBalanceCurrent: borrowBalanceCurrent,\n balanceOfUnderlying: balanceOfUnderlying,\n tokenBalance: tokenBalance,\n tokenAllowance: tokenAllowance\n });\n }\n\n /**\n * @notice Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlock: vToken.supplyRatePerBlock(),\n borrowRatePerBlock: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(address(vToken.comptroller()));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n return\n VTokenUnderlyingPrice({\n vToken: address(vToken),\n underlyingPrice: priceOracle.getUnderlyingPrice(address(vToken))\n });\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n (borrowState.index, borrowState.block, borrowState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenBorrowState(address(markets[i]));\n RewardTokenState memory supplyState;\n (supplyState.index, supplyState.block, supplyState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenSupplyState(address(markets[i]));\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, borrowAmount) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: borrowState.index }), ratio);\n borrowState.index = safe224(index.mantissa, \"new index overflows\");\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(supplyState.block));\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, supplyTokens) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: supplyState.index }), ratio);\n supplyState.index = safe224(index.mantissa, \"new index overflows\");\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/ApproveOrRevert.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nlibrary ApproveOrRevert {\n /// @notice Thrown if a contract is unable to approve a transfer\n error ApproveFailed();\n\n /// @notice Approves a transfer, ensuring that it is successful. This function supports non-compliant\n /// tokens like the ones that don't return a boolean value on success. Thus, such approve call supports\n /// three different kinds of tokens:\n /// * Compliant tokens that revert on failure\n /// * Compliant tokens that return false on failure\n /// * Non-compliant tokens that don't return a value\n /// @param token The contract address of the token which will be transferred\n /// @param spender The spender contract address\n /// @param amount The value of the transfer\n function approveOrRevert(IERC20Upgradeable token, address spender, uint256 amount) internal {\n bytes memory callData = abi.encodeCall(token.approve, (spender, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory result) = address(token).call(callData);\n\n if (!success || (result.length != 0 && !abi.decode(result, (bool)))) {\n revert ApproveFailed();\n }\n }\n}\n" + }, + "contracts/lib/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" + }, + "contracts/lib/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/lib/TokenDebtTracker.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n/**\n * @title TokenDebtTracker\n * @author Venus\n * @notice TokenDebtTracker is an abstract contract that handles transfers _out_ of the inheriting contract.\n * If there is an error transferring out (due to any reason, e.g. the token contract restricted the user from\n * receiving incoming transfers), the amount is recorded as a debt that can be claimed later.\n * @dev Note that the inheriting contract keeps some amount of users' tokens on its balance, so be careful when\n * using balanceOf(address(this))!\n */\nabstract contract TokenDebtTracker is Initializable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => (address user => uint256 amount)).\n * Tracks failed transfers: when a token transfer fails, we record the\n * amount of the transfer, so that the user can redeem this debt later.\n */\n mapping(IERC20Upgradeable => mapping(address => uint256)) public tokenDebt;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => uint256 amount) shows how many\n * tokens the contract owes to all users. This is useful for accounting to\n * understand how much of balanceOf(address(this)) is already owed to users.\n */\n mapping(IERC20Upgradeable => uint256) public totalTokenDebt;\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[48] private __gap;\n\n /**\n * @notice Emitted when the contract's debt to the user is increased due to a failed transfer\n * @param token Token address\n * @param user User address\n * @param amount The amount of debt added\n */\n event TokenDebtAdded(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Emitted when a user claims tokens that the contract owes them\n * @param token Token address\n * @param user User address\n * @param amount The amount transferred\n */\n event TokenDebtClaimed(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Thrown if the user tries to claim more tokens than they are owed\n * @param token The token the user is trying to claim\n * @param owedAmount The amount of tokens the contract owes to the user\n * @param amount The amount of tokens the user is trying to claim\n */\n error InsufficientDebt(address token, address user, uint256 owedAmount, uint256 amount);\n\n /**\n * @notice Thrown if trying to transfer more tokens than the contract currently has\n * @param token The token the contract is trying to transfer\n * @param recipient The recipient of the transfer\n * @param amount The amount of tokens the contract is trying to transfer\n * @param availableBalance The amount of tokens the contract currently has\n */\n error InsufficientBalance(address token, address recipient, uint256 amount, uint256 availableBalance);\n\n /**\n * @notice Transfers the tokens we owe to msg.sender, if any\n * @param token The token to claim\n * @param amount_ The amount of tokens to claim (or max uint256 to claim all)\n * @custom:error InsufficientDebt The contract doesn't have enough debt to the user\n */\n function claimTokenDebt(IERC20Upgradeable token, uint256 amount_) external {\n uint256 owedAmount = tokenDebt[token][msg.sender];\n uint256 amount = (amount_ == type(uint256).max ? owedAmount : amount_);\n if (amount > owedAmount) {\n revert InsufficientDebt(address(token), msg.sender, owedAmount, amount);\n }\n unchecked {\n // Safe because we revert if amount > owedAmount above\n tokenDebt[token][msg.sender] = owedAmount - amount;\n }\n totalTokenDebt[token] -= amount;\n emit TokenDebtClaimed(address(token), msg.sender, amount);\n token.safeTransfer(msg.sender, amount);\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function __TokenDebtTracker_init() internal onlyInitializing {\n __TokenDebtTracker_init_unchained();\n }\n\n // solhint-disable-next-line func-name-mixedcase, no-empty-blocks\n function __TokenDebtTracker_init_unchained() internal onlyInitializing {}\n\n /**\n * @dev Transfers tokens to the recipient if the contract has enough balance, or\n * records the debt if the transfer fails due to reasons unrelated to the contract's\n * balance (e.g. if the token forbids transfers to the recipient).\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @custom:error InsufficientBalance The contract doesn't have enough balance to transfer\n */\n function _transferOutOrTrackDebt(IERC20Upgradeable token, address to, uint256 amount) internal {\n uint256 balance = token.balanceOf(address(this));\n if (balance < amount) {\n revert InsufficientBalance(address(token), address(this), amount, balance);\n }\n _transferOutOrTrackDebtSkippingBalanceCheck(token, to, amount);\n }\n\n /**\n * @dev Transfers tokens to the recipient, or records the debt if the transfer fails\n * due to any reason, including insufficient balance.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n */\n function _transferOutOrTrackDebtSkippingBalanceCheck(IERC20Upgradeable token, address to, uint256 amount) internal {\n // We can't use safeTransfer here because we can't try-catch internal calls\n bool success = _tryTransferOut(token, to, amount);\n if (!success) {\n tokenDebt[token][to] += amount;\n totalTokenDebt[token] += amount;\n emit TokenDebtAdded(address(token), to, amount);\n }\n }\n\n /**\n * @dev Either transfers tokens to the recepient or returns false. Supports tokens\n * thet revert or return false to indicate failure, and the non-compliant ones\n * that do not return any value.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @return true if the transfer succeeded, false otherwise\n */\n function _tryTransferOut(IERC20Upgradeable token, address to, uint256 amount) private returns (bool) {\n bytes memory callData = abi.encodeCall(token.transfer, (to, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = address(token).call(callData);\n return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n }\n}\n" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\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\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\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 /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.approve(vTokenAddress, 0);\n underlying.approve(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\n/**\n * @title PoolRegistryInterface\n * @author Venus\n * @notice Interface implemented by `PoolRegistry`.\n */\ninterface PoolRegistryInterface {\n /**\n * @notice Struct for a Venus interest rate pool.\n */\n struct VenusPool {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n }\n\n /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each block for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block.\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, MaxLoopsLimitHelper {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per block\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller private comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n function initializeMarket(address vToken) external onlyComptroller {\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlock(address[],uint32[],uint32[])\");\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumber();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\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 */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumber = getBlockNumber();\n uint256 deltaBlocks = sub_(blockNumber, lastContributorBlock[contributor]);\n if (deltaBlocks > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocks, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumber;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n function getBlockNumber() public view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumber();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN accrued by a supplier and possibly transfer it to them.\n * @param vToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n uint256 supplyIndex = supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n uint256 borrowIndex = borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(supplyState.block));\n\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n supplyState.index = safe224(\n add_(Double({ mantissa: supplyState.index }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n supplyState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n supplyState.block = blockNumber;\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint32 blockNumber = safe32(getBlockNumber(), \"block number exceeds 32 bits\");\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(uint256(blockNumber), uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n borrowState.index = safe224(\n add_(Double({ mantissa: borrowState.index }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n borrowState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n borrowState.block = blockNumber;\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n}\n" + }, + "contracts/RiskFund/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 swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external returns (uint256);\n\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updateAssetsState(address comptroller, address asset) external;\n\n function convertibleBaseAsset() external view returns (address);\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n" + }, + "contracts/RiskFund/ReserveHelpers.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { VToken } from \"../VToken.sol\";\n\ncontract ReserveHelpers is Ownable2StepUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 private constant NOT_ENTERED = 1;\n\n uint256 private constant ENTERED = 2;\n\n // Address of the core pool's comptroller\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n // Address of the VBNB\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable VBNB;\n\n // Address of the native wrapped token\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_WRAPPED;\n\n // Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools).\n mapping(address => uint256) public assetsReserves;\n\n // Store the asset's reserve per pool in the ProtocolShareReserve.\n // Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal _poolsAssetsReserves;\n\n // Address of pool registry contract\n address public poolRegistry;\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n uint256 internal status;\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 */\n uint256[46] private __gap;\n\n /// @notice Event emitted after the update of the assets reserves.\n /// @param comptroller Pool's Comptroller address\n /// @param asset Token address\n /// @param amount An amount by which the reserves have increased\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice event emitted on sweep token success\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(status != ENTERED, \"re-entered\");\n status = ENTERED;\n _;\n status = NOT_ENTERED;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address corePoolComptroller_, address vbnb_, address nativeWrapped_) {\n ensureNonzeroAddress(corePoolComptroller_);\n ensureNonzeroAddress(vbnb_);\n ensureNonzeroAddress(nativeWrapped_);\n\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\n VBNB = vbnb_;\n NATIVE_WRAPPED = nativeWrapped_;\n }\n\n /**\n * @notice A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input\n * @param _token The address of the BEP-20 token to sweep\n * @param _to Recipient of the output tokens.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n * @custom:access Only Owner\n */\n function sweepToken(address _token, address _to) external onlyOwner nonReentrant {\n ensureNonzeroAddress(_to);\n uint256 balanceDfference_;\n uint256 balance_ = IERC20Upgradeable(_token).balanceOf(address(this));\n\n require(balance_ > assetsReserves[_token], \"ReserveHelpers: Zero surplus tokens\");\n unchecked {\n balanceDfference_ = balance_ - assetsReserves[_token];\n }\n\n emit SweepToken(_token, _to, balanceDfference_);\n IERC20Upgradeable(_token).safeTransfer(_to, balanceDfference_);\n }\n\n /**\n * @notice 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 Asset's reserve in risk fund.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256) {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][asset];\n }\n\n /**\n * @notice 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 * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function updateAssetsState(address comptroller, address asset) public virtual {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n address poolRegistry_ = poolRegistry;\n require(poolRegistry_ != address(0), \"ReserveHelpers: Pool Registry address is not set\");\n require(ensureAssetListed(comptroller, asset), \"ReserveHelpers: The pool doesn't support the asset\");\n\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n assetsReserves[asset] += balanceDifference;\n _poolsAssetsReserves[comptroller][asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference);\n }\n }\n\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\n VToken[] memory coreMarkets = ComptrollerInterface(CORE_POOL_COMPTROLLER).getAllMarkets();\n\n for (uint256 i; i < coreMarkets.length; ++i) {\n isAssetListed = (VBNB == address(coreMarkets[i]))\n ? (tokenAddress == NATIVE_WRAPPED)\n : (coreMarkets[i].underlying() == tokenAddress);\n\n if (isAssetListed) {\n break;\n }\n }\n }\n\n /// @notice 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 function ensureAssetListed(address comptroller, address asset) internal view returns (bool) {\n if (comptroller == CORE_POOL_COMPTROLLER) {\n return isAssetListedInCore(asset);\n }\n\n return PoolRegistryInterface(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\n }\n}\n" + }, + "contracts/RiskFund/RiskFund.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 { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { IRiskFund } from \"./IRiskFund.sol\";\nimport { ReserveHelpers } from \"./ReserveHelpers.sol\";\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { IPancakeswapV2Router } from \"../IPancakeswapV2Router.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { ApproveOrRevert } from \"../lib/ApproveOrRevert.sol\";\n\n/**\n * @title RiskFund\n * @author Venus\n * @notice Contract with basic features to track/hold different assets for different Comptrollers.\n * @dev This contract does not support BNB.\n */\ncontract RiskFund is AccessControlledV8, ExponentialNoError, ReserveHelpers, MaxLoopsLimitHelper, IRiskFund {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using ApproveOrRevert for IERC20Upgradeable;\n\n address public convertibleBaseAsset;\n address public shortfall;\n address public pancakeSwapRouter;\n uint256 public minAmountToConvert;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when shortfall contract address is updated\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\n\n /// @notice Emitted when convertible base asset is updated\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\n\n /// @notice Emitted when PancakeSwap router contract address is updated\n event PancakeSwapRouterUpdated(address indexed oldPancakeSwapRouter, address indexed newPancakeSwapRouter);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Emitted when pools assets are swapped\n event SwappedPoolsAssets(address[] markets, uint256[] amountsOutMin, uint256 totalAmount);\n\n /// @notice Emitted when reserves are transferred for auction\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\n\n /// @dev Note that the contract is upgradeable. Use initialize() or reinitializers\n /// to set the state variables.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address corePoolComptroller_,\n address vbnb_,\n address nativeWrapped_\n ) ReserveHelpers(corePoolComptroller_, vbnb_, nativeWrapped_) {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner.\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @param minAmountToConvert_ Minimum amount assets must be worth to convert into base asset\n * @param convertibleBaseAsset_ Address of the base asset\n * @param accessControlManager_ Address of the access control contract\n * @param loopsLimit_ Limit for the loops in the contract to avoid DOS\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n */\n function initialize(\n address pancakeSwapRouter_,\n uint256 minAmountToConvert_,\n address convertibleBaseAsset_,\n address accessControlManager_,\n uint256 loopsLimit_\n ) external initializer {\n ensureNonzeroAddress(pancakeSwapRouter_);\n ensureNonzeroAddress(convertibleBaseAsset_);\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n require(loopsLimit_ > 0, \"Risk Fund: Loops limit can not be zero\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n pancakeSwapRouter = pancakeSwapRouter_;\n minAmountToConvert = minAmountToConvert_;\n convertibleBaseAsset = convertibleBaseAsset_;\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice 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 address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Shortfall contract address setter\n * @param shortfallContractAddress_ Address of the auction contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n */\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\n ensureNonzeroAddress(shortfallContractAddress_);\n\n address oldShortfallContractAddress = shortfall;\n shortfall = shortfallContractAddress_;\n emit ShortfallContractUpdated(oldShortfallContractAddress, shortfallContractAddress_);\n }\n\n /**\n * @notice PancakeSwap router address setter\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n */\n function setPancakeSwapRouter(address pancakeSwapRouter_) external onlyOwner {\n ensureNonzeroAddress(pancakeSwapRouter_);\n address oldPancakeSwapRouter = pancakeSwapRouter;\n pancakeSwapRouter = pancakeSwapRouter_;\n emit PancakeSwapRouterUpdated(oldPancakeSwapRouter, pancakeSwapRouter_);\n }\n\n /**\n * @notice Min amount to convert setter\n * @param minAmountToConvert_ Min amount to convert.\n */\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n uint256 oldMinAmountToConvert = minAmountToConvert;\n minAmountToConvert = minAmountToConvert_;\n emit MinAmountToConvertUpdated(oldMinAmountToConvert, minAmountToConvert_);\n }\n\n /**\n * @notice Sets a new convertible base asset\n * @param _convertibleBaseAsset Address for new convertible base asset.\n */\n function setConvertibleBaseAsset(address _convertibleBaseAsset) external {\n _checkAccessAllowed(\"setConvertibleBaseAsset(address)\");\n require(_convertibleBaseAsset != address(0), \"Risk Fund: new convertible base asset address invalid\");\n\n address oldConvertibleBaseAsset = convertibleBaseAsset;\n convertibleBaseAsset = _convertibleBaseAsset;\n\n emit ConvertibleBaseAssetUpdated(oldConvertibleBaseAsset, _convertibleBaseAsset);\n }\n\n /**\n * @notice Swap array of pool assets into base asset's tokens of at least a minimum amount\n * @param markets Array of vTokens whose assets to swap for base asset\n * @param amountsOutMin Minimum amount to receive for swap\n * @param paths A path consisting of PCS token pairs for each swap\n * @param deadline Deadline for the swap\n * @return Number of swapped tokens\n * @custom:error ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\n */\n function swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external override nonReentrant returns (uint256) {\n _checkAccessAllowed(\"swapPoolsAssets(address[],uint256[],address[][],uint256)\");\n require(deadline >= block.timestamp, \"Risk fund: deadline passed\");\n address poolRegistry_ = poolRegistry;\n ensureNonzeroAddress(poolRegistry_);\n require(markets.length == amountsOutMin.length, \"Risk fund: markets and amountsOutMin are unequal lengths\");\n require(markets.length == paths.length, \"Risk fund: markets and paths are unequal lengths\");\n\n uint256 totalAmount;\n uint256 marketsCount = markets.length;\n\n _ensureMaxLoops(marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n address comptroller = address(VToken(markets[i]).comptroller());\n\n PoolRegistry.VenusPool memory pool = PoolRegistry(poolRegistry_).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n require(Comptroller(comptroller).isMarketListed(VToken(markets[i])), \"market is not listed\");\n\n uint256 swappedTokens = _swapAsset(VToken(markets[i]), comptroller, amountsOutMin[i], paths[i]);\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] += swappedTokens;\n assetsReserves[convertibleBaseAsset] += swappedTokens;\n totalAmount = totalAmount + swappedTokens;\n }\n\n emit SwappedPoolsAssets(markets, amountsOutMin, totalAmount);\n\n return totalAmount;\n }\n\n /**\n * @notice Transfer tokens for auction.\n * @param comptroller Comptroller of the pool.\n * @param amount Amount to be transferred to auction contract.\n * @return Number reserved tokens.\n */\n function transferReserveForAuction(\n address comptroller,\n uint256 amount\n ) external override nonReentrant returns (uint256) {\n address shortfall_ = shortfall;\n require(msg.sender == shortfall_, \"Risk fund: Only callable by Shortfall contract\");\n require(\n amount <= _poolsAssetsReserves[comptroller][convertibleBaseAsset],\n \"Risk Fund: Insufficient pool reserve.\"\n );\n unchecked {\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] =\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] -\n amount;\n }\n unchecked {\n assetsReserves[convertibleBaseAsset] = assetsReserves[convertibleBaseAsset] - amount;\n }\n\n emit TransferredReserveForAuction(comptroller, amount);\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall_, amount);\n\n return amount;\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 */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\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 require(ComptrollerInterface(comptroller).isComptroller(), \"Risk Fund: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][convertibleBaseAsset];\n }\n\n /**\n * @notice Update the reserve of the asset for the specific pool after transferring to risk fund.\n * @param comptroller Comptroller address(pool).\n * @param asset Asset address.\n */\n function updateAssetsState(address comptroller, address asset) public override(IRiskFund, ReserveHelpers) {\n super.updateAssetsState(comptroller, asset);\n }\n\n /**\n * @dev Swap single asset to base asset.\n * @param vToken VToken\n * @param comptroller Comptroller address\n * @param amountOutMin Minimum amount to receive for swap\n * @param path A path for the swap consisting of PCS token pairs\n * @return Number of swapped tokens.\n */\n function _swapAsset(\n VToken vToken,\n address comptroller,\n uint256 amountOutMin,\n address[] calldata path\n ) internal returns (uint256) {\n require(amountOutMin != 0, \"RiskFund: amountOutMin must be greater than 0 to swap vToken\");\n uint256 totalAmount;\n\n address underlyingAsset = vToken.underlying();\n address convertibleBaseAsset_ = convertibleBaseAsset;\n uint256 balanceOfUnderlyingAsset = _poolsAssetsReserves[comptroller][underlyingAsset];\n\n if (balanceOfUnderlyingAsset == 0) {\n return 0;\n }\n\n ResilientOracleInterface oracle = ComptrollerViewInterface(comptroller).oracle();\n oracle.updateAssetPrice(convertibleBaseAsset_);\n Exp memory baseAssetPrice = Exp({ mantissa: oracle.getPrice(convertibleBaseAsset_) });\n uint256 amountOutMinInUsd = mul_ScalarTruncate(baseAssetPrice, amountOutMin);\n\n require(amountOutMinInUsd >= minAmountToConvert, \"RiskFund: minAmountToConvert violated\");\n\n assetsReserves[underlyingAsset] -= balanceOfUnderlyingAsset;\n _poolsAssetsReserves[comptroller][underlyingAsset] -= balanceOfUnderlyingAsset;\n\n if (underlyingAsset != convertibleBaseAsset_) {\n require(path[0] == underlyingAsset, \"RiskFund: swap path must start with the underlying asset\");\n require(\n path[path.length - 1] == convertibleBaseAsset_,\n \"RiskFund: finally path must be convertible base asset\"\n );\n address pancakeSwapRouter_ = pancakeSwapRouter;\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, 0);\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, balanceOfUnderlyingAsset);\n uint256[] memory amounts = IPancakeswapV2Router(pancakeSwapRouter_).swapExactTokensForTokens(\n balanceOfUnderlyingAsset,\n amountOutMin,\n path,\n address(this),\n block.timestamp\n );\n totalAmount = amounts[path.length - 1];\n } else {\n totalAmount = balanceOfUnderlyingAsset;\n }\n\n return totalAmount;\n }\n}\n" + }, + "contracts/Shortfall/Shortfall.sol": { + "content": "/// @notice SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { IRiskFund } from \"../RiskFund/IRiskFund.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { TokenDebtTracker } from \"../lib/TokenDebtTracker.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\nimport { EXP_SCALE } from \"../lib/constants.sol\";\n\n/**\n * @title Shortfall\n * @author Venus\n * @notice Shortfall is an auction contract designed to auction off the `convertibleBaseAsset` accumulated in `RiskFund`. The `convertibleBaseAsset`\n * is auctioned in exchange for users paying off the pool's bad debt. An auction can be started by anyone once a pool's bad debt has reached a minimum value.\n * This value is set and can be changed by the authorized accounts. If the pool’s bad debt exceeds the risk fund plus a 10% incentive, then the auction winner\n * is determined by who will pay off the largest percentage of the pool's bad debt. The auction winner then exchanges for the entire risk fund. Otherwise,\n * if the risk fund covers the pool's bad debt plus the 10% incentive, then the auction winner is determined by who will take the smallest percentage of the\n * risk fund in exchange for paying off all the pool's bad debt.\n */\ncontract Shortfall is Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGuardUpgradeable, TokenDebtTracker {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Type of auction\n enum AuctionType {\n LARGE_POOL_DEBT,\n LARGE_RISK_FUND\n }\n\n /// @notice Status of auction\n enum AuctionStatus {\n NOT_STARTED,\n STARTED,\n ENDED\n }\n\n /// @notice Auction metadata\n struct Auction {\n uint256 startBlock;\n AuctionType auctionType;\n AuctionStatus status;\n VToken[] markets;\n uint256 seizedRiskFund;\n address highestBidder;\n uint256 highestBidBps;\n uint256 highestBidBlock;\n uint256 startBidBps;\n mapping(VToken => uint256) marketDebt;\n mapping(VToken => uint256) bidAmount;\n }\n\n /// @dev Max basis points i.e., 100%\n uint256 private constant MAX_BPS = 10000;\n\n uint256 private constant DEFAULT_NEXT_BIDDER_BLOCK_LIMIT = 100;\n\n uint256 private constant DEFAULT_WAIT_FOR_FIRST_BIDDER = 100;\n\n uint256 private constant DEFAULT_INCENTIVE_BPS = 1000; // 10%\n\n /// @notice Pool registry address\n address public poolRegistry;\n\n /// @notice Risk fund address\n IRiskFund public riskFund;\n\n /// @notice Minimum USD debt in pool for shortfall to trigger\n uint256 public minimumPoolBadDebt;\n\n /// @notice Incentive to auction participants, initial value set to 1000 or 10%\n uint256 public incentiveBps;\n\n /// @notice Time to wait for next bidder. Initially waits for 100 blocks\n uint256 public nextBidderBlockLimit;\n\n /// @notice Boolean of if auctions are paused\n bool public auctionsPaused;\n\n /// @notice Time to wait for first bidder. Initially waits for 100 blocks\n uint256 public waitForFirstBidder;\n\n /// @notice Auctions for each pool\n mapping(address => Auction) public auctions;\n\n /// @notice Emitted when a auction starts\n event AuctionStarted(\n address indexed comptroller,\n uint256 auctionStartBlock,\n AuctionType auctionType,\n VToken[] markets,\n uint256[] marketsDebt,\n uint256 seizedRiskFund,\n uint256 startBidBps\n );\n\n /// @notice Emitted when a bid is placed\n event BidPlaced(address indexed comptroller, uint256 auctionStartBlock, uint256 bidBps, address indexed bidder);\n\n /// @notice Emitted when a auction is completed\n event AuctionClosed(\n address indexed comptroller,\n uint256 auctionStartBlock,\n address indexed highestBidder,\n uint256 highestBidBps,\n uint256 seizedRiskFind,\n VToken[] markets,\n uint256[] marketDebt\n );\n\n /// @notice Emitted when a auction is restarted\n event AuctionRestarted(address indexed comptroller, uint256 auctionStartBlock);\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when minimum pool bad debt is updated\n event MinimumPoolBadDebtUpdated(uint256 oldMinimumPoolBadDebt, uint256 newMinimumPoolBadDebt);\n\n /// @notice Emitted when wait for first bidder block count is updated\n event WaitForFirstBidderUpdated(uint256 oldWaitForFirstBidder, uint256 newWaitForFirstBidder);\n\n /// @notice Emitted when next bidder block limit is updated\n event NextBidderBlockLimitUpdated(uint256 oldNextBidderBlockLimit, uint256 newNextBidderBlockLimit);\n\n /// @notice Emitted when incentiveBps is updated\n event IncentiveBpsUpdated(uint256 oldIncentiveBps, uint256 newIncentiveBps);\n\n /// @notice Emitted when auctions are paused\n event AuctionsPaused(address sender);\n\n /// @notice Emitted when auctions are unpaused\n event AuctionsResumed(address sender);\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 /**\n * @notice Initialize the shortfall contract\n * @param riskFund_ RiskFund contract address\n * @param minimumPoolBadDebt_ Minimum bad debt in base asset for a pool to start auction\n * @param accessControlManager_ AccessControlManager contract address\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when risk fund address is zero\n */\n function initialize(\n IRiskFund riskFund_,\n uint256 minimumPoolBadDebt_,\n address accessControlManager_\n ) external initializer {\n ensureNonzeroAddress(address(riskFund_));\n require(minimumPoolBadDebt_ != 0, \"invalid minimum pool bad debt\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n __ReentrancyGuard_init();\n __TokenDebtTracker_init();\n minimumPoolBadDebt = minimumPoolBadDebt_;\n riskFund = riskFund_;\n waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER;\n nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_LIMIT;\n incentiveBps = DEFAULT_INCENTIVE_BPS;\n auctionsPaused = false;\n }\n\n /**\n * @notice Place a bid greater than the previous in an ongoing auction\n * @param comptroller Comptroller address of the pool\n * @param bidBps The bid percent of the risk fund or bad debt depending on auction type\n * @param auctionStartBlock The block number when auction started\n * @custom:event Emits BidPlaced event on success\n */\n function placeBid(address comptroller, uint256 bidBps, uint256 auctionStartBlock) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(auction.startBlock == auctionStartBlock, \"auction has been restarted\");\n require(_isStarted(auction), \"no on-going auction\");\n require(!_isStale(auction), \"auction is stale, restart it\");\n require(bidBps > 0, \"basis points cannot be zero\");\n require(bidBps <= MAX_BPS, \"basis points cannot be more than 10000\");\n require(\n (auction.auctionType == AuctionType.LARGE_POOL_DEBT &&\n ((auction.highestBidder != address(0) && bidBps > auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps >= auction.startBidBps))) ||\n (auction.auctionType == AuctionType.LARGE_RISK_FUND &&\n ((auction.highestBidder != address(0) && bidBps < auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps <= auction.startBidBps))),\n \"your bid is not the highest\"\n );\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n if (auction.highestBidder != address(0)) {\n _transferOutOrTrackDebt(erc20, auction.highestBidder, auction.bidAmount[auction.markets[i]]);\n }\n uint256 balanceBefore = erc20.balanceOf(address(this));\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n uint256 currentBidAmount = ((auction.marketDebt[auction.markets[i]] * bidBps) / MAX_BPS);\n erc20.safeTransferFrom(msg.sender, address(this), currentBidAmount);\n } else {\n erc20.safeTransferFrom(msg.sender, address(this), auction.marketDebt[auction.markets[i]]);\n }\n\n uint256 balanceAfter = erc20.balanceOf(address(this));\n auction.bidAmount[auction.markets[i]] = balanceAfter - balanceBefore;\n }\n\n auction.highestBidder = msg.sender;\n auction.highestBidBps = bidBps;\n auction.highestBidBlock = block.number;\n\n emit BidPlaced(comptroller, auction.startBlock, bidBps, msg.sender);\n }\n\n /**\n * @notice Close an auction\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionClosed event on successful close\n */\n function closeAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(_isStarted(auction), \"no on-going auction\");\n require(\n block.number > auction.highestBidBlock + nextBidderBlockLimit && auction.highestBidder != address(0),\n \"waiting for next bidder. cannot close auction\"\n );\n\n uint256 marketsCount = auction.markets.length;\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n\n auction.status = AuctionStatus.ENDED;\n\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n uint256 balanceBefore = erc20.balanceOf(address(auction.markets[i]));\n erc20.safeTransfer(address(auction.markets[i]), auction.bidAmount[auction.markets[i]]);\n uint256 balanceAfter = erc20.balanceOf(address(auction.markets[i]));\n marketsDebt[i] = balanceAfter - balanceBefore;\n\n auction.markets[i].badDebtRecovered(marketsDebt[i]);\n }\n\n uint256 riskFundBidAmount;\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n riskFundBidAmount = auction.seizedRiskFund;\n } else {\n riskFundBidAmount = (auction.seizedRiskFund * auction.highestBidBps) / MAX_BPS;\n }\n\n address convertibleBaseAsset = riskFund.convertibleBaseAsset();\n\n uint256 transferredAmount = riskFund.transferReserveForAuction(comptroller, riskFundBidAmount);\n _transferOutOrTrackDebt(IERC20Upgradeable(convertibleBaseAsset), auction.highestBidder, riskFundBidAmount);\n\n emit AuctionClosed(\n comptroller,\n auction.startBlock,\n auction.highestBidder,\n auction.highestBidBps,\n transferredAmount,\n auction.markets,\n marketsDebt\n );\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionStarted event on success\n * @custom:event Errors if auctions are paused\n */\n function startAuction(address comptroller) external nonReentrant {\n require(!auctionsPaused, \"Auctions are paused\");\n _startAuction(comptroller);\n }\n\n /**\n * @notice Restart an auction\n * @param comptroller Address of the pool\n * @custom:event Emits AuctionRestarted event on successful restart\n */\n function restartAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(!auctionsPaused, \"auctions are paused\");\n require(_isStarted(auction), \"no on-going auction\");\n require(_isStale(auction), \"you need to wait for more time for first bidder\");\n\n auction.status = AuctionStatus.ENDED;\n\n emit AuctionRestarted(comptroller, auction.startBlock);\n _startAuction(comptroller);\n }\n\n /**\n * @notice Update next bidder block limit which is used determine when an auction can be closed\n * @param _nextBidderBlockLimit New next bidder block limit\n * @custom:event Emits NextBidderBlockLimitUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateNextBidderBlockLimit(uint256 _nextBidderBlockLimit) external {\n _checkAccessAllowed(\"updateNextBidderBlockLimit(uint256)\");\n require(_nextBidderBlockLimit != 0, \"_nextBidderBlockLimit must not be 0\");\n uint256 oldNextBidderBlockLimit = nextBidderBlockLimit;\n nextBidderBlockLimit = _nextBidderBlockLimit;\n emit NextBidderBlockLimitUpdated(oldNextBidderBlockLimit, _nextBidderBlockLimit);\n }\n\n /**\n * @notice Updates the incentive BPS\n * @param _incentiveBps New incentive BPS\n * @custom:event Emits IncentiveBpsUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateIncentiveBps(uint256 _incentiveBps) external {\n _checkAccessAllowed(\"updateIncentiveBps(uint256)\");\n require(_incentiveBps != 0, \"incentiveBps must not be 0\");\n uint256 oldIncentiveBps = incentiveBps;\n incentiveBps = _incentiveBps;\n emit IncentiveBpsUpdated(oldIncentiveBps, _incentiveBps);\n }\n\n /**\n * @notice Update minimum pool bad debt to start auction\n * @param _minimumPoolBadDebt Minimum bad debt in the base asset for a pool to start auction\n * @custom:event Emits MinimumPoolBadDebtUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateMinimumPoolBadDebt(uint256 _minimumPoolBadDebt) external {\n _checkAccessAllowed(\"updateMinimumPoolBadDebt(uint256)\");\n uint256 oldMinimumPoolBadDebt = minimumPoolBadDebt;\n minimumPoolBadDebt = _minimumPoolBadDebt;\n emit MinimumPoolBadDebtUpdated(oldMinimumPoolBadDebt, _minimumPoolBadDebt);\n }\n\n /**\n * @notice Update wait for first bidder block count. If the first bid is not made within this limit, the auction is closed and needs to be restarted\n * @param _waitForFirstBidder New wait for first bidder block count\n * @custom:event Emits WaitForFirstBidderUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateWaitForFirstBidder(uint256 _waitForFirstBidder) external {\n _checkAccessAllowed(\"updateWaitForFirstBidder(uint256)\");\n uint256 oldWaitForFirstBidder = waitForFirstBidder;\n waitForFirstBidder = _waitForFirstBidder;\n emit WaitForFirstBidderUpdated(oldWaitForFirstBidder, _waitForFirstBidder);\n }\n\n /**\n * @notice Update the pool registry this shortfall supports\n * @dev After Pool Registry is deployed we need to set the pool registry address\n * @param poolRegistry_ Address of pool registry contract\n * @custom:event Emits PoolRegistryUpdated on success\n * @custom:access Restricted to owner\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function updatePoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Pause auctions. This disables starting new auctions but lets the current auction finishes\n * @custom:event Emits AuctionsPaused on success\n * @custom:error Errors is auctions are paused\n * @custom:access Restricted by ACM\n */\n function pauseAuctions() external {\n _checkAccessAllowed(\"pauseAuctions()\");\n require(!auctionsPaused, \"Auctions are already paused\");\n auctionsPaused = true;\n emit AuctionsPaused(msg.sender);\n }\n\n /**\n * @notice Resume paused auctions.\n * @custom:event Emits AuctionsResumed on success\n * @custom:error Errors is auctions are active\n * @custom:access Restricted by ACM\n */\n function resumeAuctions() external {\n _checkAccessAllowed(\"resumeAuctions()\");\n require(auctionsPaused, \"Auctions are not paused\");\n auctionsPaused = false;\n emit AuctionsResumed(msg.sender);\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n */\n function _startAuction(address comptroller) internal {\n PoolRegistryInterface.VenusPool memory pool = PoolRegistry(poolRegistry).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n\n Auction storage auction = auctions[comptroller];\n require(\n auction.status == AuctionStatus.NOT_STARTED || auction.status == AuctionStatus.ENDED,\n \"auction is on-going\"\n );\n\n auction.highestBidBps = 0;\n auction.highestBidBlock = 0;\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = auction.markets[i];\n auction.marketDebt[vToken] = 0;\n }\n\n delete auction.markets;\n\n VToken[] memory vTokens = _getAllMarkets(comptroller);\n marketsCount = vTokens.length;\n ResilientOracleInterface priceOracle = _getPriceOracle(comptroller);\n uint256 poolBadDebt;\n\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n auction.markets = new VToken[](marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n uint256 marketBadDebt = vTokens[i].badDebt();\n\n priceOracle.updatePrice(address(vTokens[i]));\n uint256 usdValue = (priceOracle.getUnderlyingPrice(address(vTokens[i])) * marketBadDebt) / EXP_SCALE;\n\n poolBadDebt = poolBadDebt + usdValue;\n auction.markets[i] = vTokens[i];\n auction.marketDebt[vTokens[i]] = marketBadDebt;\n marketsDebt[i] = marketBadDebt;\n }\n\n require(poolBadDebt >= minimumPoolBadDebt, \"pool bad debt is too low\");\n\n priceOracle.updateAssetPrice(riskFund.convertibleBaseAsset());\n uint256 riskFundBalance = (priceOracle.getPrice(riskFund.convertibleBaseAsset()) *\n riskFund.getPoolsBaseAssetReserves(comptroller)) / EXP_SCALE;\n uint256 remainingRiskFundBalance = riskFundBalance;\n uint256 badDebtPlusIncentive = poolBadDebt + ((poolBadDebt * incentiveBps) / MAX_BPS);\n if (badDebtPlusIncentive >= riskFundBalance) {\n auction.startBidBps =\n (MAX_BPS * MAX_BPS * remainingRiskFundBalance) /\n (poolBadDebt * (MAX_BPS + incentiveBps));\n remainingRiskFundBalance = 0;\n auction.auctionType = AuctionType.LARGE_POOL_DEBT;\n } else {\n uint256 maxSeizeableRiskFundBalance = badDebtPlusIncentive;\n\n remainingRiskFundBalance = remainingRiskFundBalance - maxSeizeableRiskFundBalance;\n auction.auctionType = AuctionType.LARGE_RISK_FUND;\n auction.startBidBps = MAX_BPS;\n }\n\n auction.seizedRiskFund = riskFundBalance - remainingRiskFundBalance;\n auction.startBlock = block.number;\n auction.status = AuctionStatus.STARTED;\n auction.highestBidder = address(0);\n\n emit AuctionStarted(\n comptroller,\n auction.startBlock,\n auction.auctionType,\n auction.markets,\n marketsDebt,\n auction.seizedRiskFund,\n auction.startBidBps\n );\n }\n\n /**\n * @dev Returns the price oracle of the pool\n * @param comptroller Address of the pool's comptroller\n * @return oracle The pool's price oracle\n */\n function _getPriceOracle(address comptroller) internal view returns (ResilientOracleInterface) {\n return ResilientOracleInterface(ComptrollerViewInterface(comptroller).oracle());\n }\n\n /**\n * @dev Returns all markets of the pool\n * @param comptroller Address of the pool's comptroller\n * @return markets The pool's markets as VToken array\n */\n function _getAllMarkets(address comptroller) internal view returns (VToken[] memory) {\n return ComptrollerInterface(comptroller).getAllMarkets();\n }\n\n /**\n * @dev Checks if the auction has started\n * @param auction The auction to query the status for\n * @return True if the auction has started\n */\n function _isStarted(Auction storage auction) internal view returns (bool) {\n return auction.status == AuctionStatus.STARTED;\n }\n\n /**\n * @dev Checks if the auction is stale, i.e. there's no bidder and the auction\n * was started more than waitForFirstBidder blocks ago.\n * @param auction The auction to query the status for\n * @return True if the auction is stale\n */\n function _isStale(Auction storage auction) internal view returns (bool) {\n bool noBidder = auction.highestBidder == address(0);\n return noBidder && (block.number > auction.startBlock + waitForFirstBidder);\n }\n}\n" + }, + "contracts/test/ComptrollerHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\ncontract ComptrollerHarness is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function harnessFastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n}\n\ncontract EchoTypesComptroller {\n function stringy(string memory s) public pure returns (string memory) {\n return s;\n }\n\n function addresses(address a) public pure returns (address) {\n return a;\n }\n\n function booly(bool b) public pure returns (bool) {\n return b;\n }\n\n function listOInts(uint256[] memory u) public pure returns (uint256[] memory) {\n return u;\n }\n\n function reverty() public pure {\n require(false, \"gotcha sucka\");\n }\n}\n" + }, + "contracts/test/ComptrollerScenario.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\n\ncontract ComptrollerScenario is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function fastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n\n function unlist(VToken vToken) public {\n markets[address(vToken)].isListed = false;\n }\n\n function membershipLength(VToken vToken) public view returns (uint256) {\n return accountAssets[address(vToken)].length;\n }\n}\n" + }, + "contracts/test/ERC20.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { SafeMath } from \"./SafeMath.sol\";\n\ninterface ERC20Base {\n event Approval(address indexed owner, address indexed spender, uint256 value);\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n function approve(address spender, uint256 value) external returns (bool);\n\n function totalSupply() external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function balanceOf(address who) external view returns (uint256);\n}\n\nabstract contract ERC20 is ERC20Base {\n function transfer(address to, uint256 value) external virtual returns (bool);\n\n function transferFrom(address from, address to, uint256 value) external virtual returns (bool);\n}\n\nabstract contract ERC20NS is ERC20Base {\n function transfer(address to, uint256 value) external virtual;\n\n function transferFrom(address from, address to, uint256 value) external virtual;\n}\n\n/**\n * @title Standard ERC20 token\n * @dev Implementation of the basic standard token.\n * See https://github.com/ethereum/EIPs/issues/20\n */\ncontract StandardToken is ERC20 {\n using SafeMath for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public override totalSupply;\n mapping(address => mapping(address => uint256)) public override allowance;\n mapping(address => uint256) public override balanceOf;\n\n constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external virtual override returns (bool) {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external virtual override returns (bool) {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n\n function approve(address _spender, uint256 amount) external virtual override returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\n/**\n * @title Non-Standard ERC20 token\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ncontract NonStandardToken is ERC20NS {\n using SafeMath for uint256;\n\n string public name;\n uint8 public decimals;\n string public symbol;\n uint256 public override totalSupply;\n mapping(address => mapping(address => uint256)) public override allowance;\n mapping(address => uint256) public override balanceOf;\n\n constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external override {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n }\n\n function transferFrom(address src, address dst, uint256 amount) external override {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n }\n\n function approve(address _spender, uint256 amount) external override returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\ncontract ERC20Harness is StandardToken {\n using SafeMath for uint256;\n // To support testing, we can specify addresses for which transferFrom should fail and return false\n mapping(address => bool) public failTransferFromAddresses;\n\n // To support testing, we allow the contract to always fail `transfer`.\n mapping(address => bool) public failTransferToAddresses;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function transfer(address dst, uint256 amount) external override returns (bool success) {\n // Added for testing purposes\n if (failTransferToAddresses[dst]) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool success) {\n // Added for testing purposes\n if (failTransferFromAddresses[src]) {\n return false;\n }\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n\n function harnessSetFailTransferFromAddress(address src, bool _fail) public {\n failTransferFromAddresses[src] = _fail;\n }\n\n function harnessSetFailTransferToAddress(address dst, bool _fail) public {\n failTransferToAddresses[dst] = _fail;\n }\n\n function harnessSetBalance(address _account, uint256 _amount) public {\n balanceOf[_account] = _amount;\n }\n}\n" + }, + "contracts/test/EvilToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { FaucetToken } from \"./FaucetToken.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title The Compound Evil Test Token\n * @author Compound\n * @notice A simple test token that fails certain operations\n */\ncontract EvilToken is FaucetToken {\n using SafeMath for uint256;\n\n bool public fail;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n fail = true;\n }\n\n function setFail(bool _fail) external {\n fail = _fail;\n }\n\n function transfer(address dst, uint256 amount) external override returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/FaucetToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { StandardToken, NonStandardToken } from \"./ERC20.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title The Compound Faucet Test Token\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetToken is StandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Compound Faucet Test Token (non-standard)\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetNonStandardToken is NonStandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n )\n NonStandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol)\n /* solhint-disable-next-line no-empty-blocks */\n {\n\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Compound Faucet Re-Entrant Test Token\n * @author Compound\n * @notice A test token that is malicious and tries to re-enter callers\n */\ncontract FaucetTokenReEntrantHarness {\n using SafeMath for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 private totalSupply_;\n mapping(address => mapping(address => uint256)) private allowance_;\n mapping(address => uint256) private balanceOf_;\n\n bytes public reEntryCallData;\n string public reEntryFun;\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n modifier reEnter(string memory funName) {\n string memory _reEntryFun = reEntryFun;\n if (compareStrings(_reEntryFun, funName)) {\n reEntryFun = \"\"; // Clear re-entry fun\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = msg.sender.call(reEntryCallData);\n // solhint-disable-next-line no-inline-assembly\n assembly {\n if eq(success, 0) {\n revert(add(returndata, 0x20), returndatasize())\n }\n }\n }\n\n _;\n }\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n bytes memory _reEntryCallData,\n string memory _reEntryFun\n ) {\n totalSupply_ = _initialAmount;\n balanceOf_[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n reEntryCallData = _reEntryCallData;\n reEntryFun = _reEntryFun;\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf_[_owner] += value;\n totalSupply_ += value;\n emit Transfer(address(this), _owner, value);\n }\n\n function totalSupply() public reEnter(\"totalSupply\") returns (uint256) {\n return totalSupply_;\n }\n\n function allowance(address owner, address spender) public reEnter(\"allowance\") returns (uint256 remaining) {\n return allowance_[owner][spender];\n }\n\n function approve(address spender, uint256 amount) public reEnter(\"approve\") returns (bool success) {\n _approve(msg.sender, spender, amount);\n return true;\n }\n\n function balanceOf(address owner) public reEnter(\"balanceOf\") returns (uint256 balance) {\n return balanceOf_[owner];\n }\n\n function transfer(address dst, uint256 amount) public reEnter(\"transfer\") returns (bool success) {\n _transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) public reEnter(\"transferFrom\") returns (bool success) {\n _transfer(src, dst, amount);\n _approve(src, msg.sender, allowance_[src][msg.sender].sub(amount));\n return true;\n }\n\n function _approve(address owner, address spender, uint256 amount) internal {\n require(spender != address(0), \"FaucetToken: approve to the zero address\");\n require(owner != address(0), \"FaucetToken: approve from the zero address\");\n allowance_[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n function _transfer(address src, address dst, uint256 amount) internal {\n require(dst != address(0), \"FaucetToken: transfer to the zero address\");\n balanceOf_[src] = balanceOf_[src].sub(amount);\n balanceOf_[dst] = balanceOf_[dst].add(amount);\n emit Transfer(src, dst, amount);\n }\n\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)));\n }\n}\n" + }, + "contracts/test/FeeToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { FaucetToken } from \"./FaucetToken.sol\";\nimport { SafeMath } from \"./SafeMath.sol\";\n\n/**\n * @title Fee Token\n * @author Compound\n * @notice A simple test token that charges fees on transfer. Used to mock USDT.\n */\ncontract FeeToken is FaucetToken {\n using SafeMath for uint256;\n\n uint256 public basisPointFee;\n address public owner;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n uint256 _basisPointFee,\n address _owner\n ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n basisPointFee = _basisPointFee;\n owner = _owner;\n }\n\n function transfer(address dst, uint256 amount) public override returns (bool) {\n uint256 fee = amount.mul(basisPointFee).div(10000);\n uint256 net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) public override returns (bool) {\n uint256 fee = amount.mul(basisPointFee).div(10000);\n uint256 net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/HarnessMaxLoopsLimitHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\n\ncontract HarnessMaxLoopsLimitHelper is MaxLoopsLimitHelper {\n function setMaxLoopsLimit(uint256 limit) external {\n _setMaxLoopsLimit(limit);\n }\n\n function ensureMaxLoops(uint256 limit) external view {\n _ensureMaxLoops(limit);\n }\n}\n" + }, + "contracts/test/lib/ApproveOrRevertHarness.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ApproveOrRevert } from \"../../lib/ApproveOrRevert.sol\";\n\ncontract ApproveOrRevertHarness {\n using ApproveOrRevert for IERC20Upgradeable;\n\n function approve(IERC20Upgradeable token, address spender, uint256 amount) external {\n token.approveOrRevert(spender, amount);\n }\n}\n" + }, + "contracts/test/lib/TokenDebtTrackerHarness.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.13;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { TokenDebtTracker } from \"../../lib/TokenDebtTracker.sol\";\n\ncontract TokenDebtTrackerHarness is TokenDebtTracker {\n function initialize() external initializer {\n __TokenDebtTracker_init();\n }\n\n function addTokenDebt(IERC20Upgradeable token, address user, uint256 amount) external {\n tokenDebt[token][user] += amount;\n totalTokenDebt[token] += amount;\n }\n\n function transferOutOrTrackDebt(IERC20Upgradeable token, address user, uint256 amount) external {\n _transferOutOrTrackDebt(token, user, amount);\n }\n\n function transferOutOrTrackDebtSkippingBalanceCheck(\n IERC20Upgradeable token,\n address user,\n uint256 amount\n ) external {\n _transferOutOrTrackDebtSkippingBalanceCheck(token, user, amount);\n }\n}\n" + }, + "contracts/test/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 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(address from, address to, uint256 value) 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(address owner, address spender, uint256 value) private {\n allowance[owner][spender] = value;\n emit Approval(owner, spender, value);\n }\n\n function _transfer(address from, address to, uint256 value) 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/MockPriceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { BinanceOracle } from \"@venusprotocol/oracle/contracts/oracles/BinanceOracle.sol\";\nimport { ChainlinkOracle } from \"@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol\";\nimport { ProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/ProtocolReserve/ProtocolShareReserve.sol\";\nimport { VToken } from \"../../VToken.sol\";\n\ncontract MockPriceOracle is ResilientOracleInterface {\n mapping(address => uint256) public assetPrices;\n\n //set price in 6 decimal precision\n // solhint-disable-next-line no-empty-blocks\n constructor() {}\n\n function setPrice(address asset, uint256 price) external {\n assetPrices[asset] = price;\n }\n\n // solhint-disable-next-line no-empty-blocks\n function updatePrice(address vToken) external override {}\n\n // solhint-disable-next-line no-empty-blocks\n function updateAssetPrice(address asset) external override {}\n\n function getPrice(address asset) external view returns (uint256) {\n return assetPrices[asset];\n }\n\n //https://compound.finance/docs/prices\n function getUnderlyingPrice(address vToken) public view override returns (uint256) {\n return assetPrices[VToken(vToken).underlying()];\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(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/test/SafeMath.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\n// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol\n// Subject to the MIT license.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c;\n unchecked {\n c = a + b;\n }\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n uint256 c;\n unchecked {\n c = a + b;\n }\n require(c >= a, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction underflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot underflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c;\n unchecked {\n c = a * b;\n }\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c;\n unchecked {\n c = a * b;\n }\n require(c / a == b, errorMessage);\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers.\n * Reverts on division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers.\n * Reverts with custom message on division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "contracts/test/UpgradedVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\n/**\n * @title Venus's VToken Contract\n * @notice VTokens which wrap an EIP-20 underlying and are immutable\n * @author Venus\n */\ncontract UpgradedVToken is VToken {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param riskManagement Addresses of risk fund contracts\n */\n\n /// @notice We added this new function to test contract upgrade\n function version() external pure returns (uint256) {\n return 2;\n }\n\n function initializeV2(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) public reinitializer(2) {\n super._initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\n );\n }\n\n function getTokenUnderlying() public view returns (address) {\n return underlying;\n }\n}\n" + }, + "contracts/test/VTokenHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\ncontract VTokenHarness is VToken {\n uint256 public blockNumber;\n uint256 public harnessExchangeRate;\n bool public harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function harnessSetAccrualBlockNumber(uint256 accrualBlockNumber_) external {\n accrualBlockNumber = accrualBlockNumber_;\n }\n\n function harnessSetBlockNumber(uint256 newBlockNumber) external {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint256 blocks) external {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint256 amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetTotalSupply(uint256 totalSupply_) external {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint256 totalBorrows_) external {\n totalBorrows = totalBorrows_;\n }\n\n function harnessSetTotalReserves(uint256 totalReserves_) external {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint256 totalSupply_, uint256 totalBorrows_, uint256 totalReserves_) external {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint256 exchangeRate) external {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address to_, bool fail_) external {\n failTransferToAddresses[to_] = fail_;\n }\n\n function harnessMintFresh(address account, uint256 mintAmount) external {\n super._mintFresh(account, account, mintAmount);\n }\n\n function harnessRedeemFresh(address payable account, uint256 vTokenAmount, uint256 underlyingAmount) external {\n super._redeemFresh(account, vTokenAmount, underlyingAmount);\n }\n\n function harnessSetAccountBorrows(address account, uint256 principal, uint256 interestIndex) external {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint256 borrowIndex_) external {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint256 borrowAmount) external {\n _borrowFresh(account, borrowAmount);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint256 repayAmount) external {\n _repayBorrowFresh(payer, account, repayAmount);\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VToken vTokenCollateral,\n bool skipLiquidityCheck\n ) external {\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n function harnessReduceReservesFresh(uint256 spreadAmount) external {\n return _reduceReservesFresh(spreadAmount);\n }\n\n function harnessSetReserveFactorFresh(uint256 newReserveFactorMantissa) external {\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) external {\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessAccountBorrows(address account) external view returns (uint256 principal, uint256 interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function getBorrowRateMaxMantissa() external pure returns (uint256) {\n return MAX_BORROW_RATE_MANTISSA;\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModel(newInterestRateModelAddress);\n }\n\n function harnessCallPreBorrowHook(uint256 amount) public {\n comptroller.preBorrowHook(address(this), msg.sender, amount);\n }\n\n function _doTransferOut(address to, uint256 amount) internal override {\n require(failTransferToAddresses[to] == false, \"HARNESS_TOKEN_TRANSFER_OUT_FAILED\");\n return super._doTransferOut(to, amount);\n }\n\n function _exchangeRateStored() internal view override returns (uint256) {\n if (harnessExchangeRateStored) {\n return harnessExchangeRate;\n }\n return super._exchangeRateStored();\n }\n\n function _getBlockNumber() internal view override returns (uint256) {\n return blockNumber;\n }\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n /**\n * Reentrancy Guard **\n */\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\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 /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\n );\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\n return true;\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\n return totalBorrows;\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n // _mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\n _redeemFresh(msg.sender, redeemTokens, 0);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _redeemFresh emits redeem-specific logs on errors, so we don't need to\n _redeemFresh(msg.sender, 0, redeemAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n _borrowFresh(msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n // _repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @dev Gracefully return if reserves already reduced in accrueInterest\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n if (reduceReservesBlockNumber == _getBlockNumber()) return;\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\n }\n\n /**\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice A public function to set new threshold of block difference after which funds will be sent to the protocol share reserve\n * @param _newReduceReservesBlockDelta block difference value\n * @custom:access Only Governance\n */\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockDelta) external {\n _checkAccessAllowed(\"setReduceReservesBlockDelta(uint256)\");\n require(_newReduceReservesBlockDelta > 0, \"Invalid Input\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockDelta);\n reduceReservesBlockDelta = _newReduceReservesBlockDelta;\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return amount The number of tokens allowed to be spent (type(uint256).max means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint256) {\n return transferAllowances[owner][spender];\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return amount The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint256) {\n return accountTokens[owner];\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return rate The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this v\n * @return rate The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\n return _exchangeRateStored();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number */\n uint256 currentBlockNumber = _getBlockNumber();\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n if (currentBlockNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentBlockNumber;\n _reduceReservesFresh(totalReservesNew);\n }\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return NO_ERROR;\n }\n\n /**\n * @notice User supplies assets into the market and receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param payer The address of the account which is sending the assets for supply\n * @param minter The address of the account which is supplying the assets\n * @param mintAmount The amount of the underlying asset to supply\n */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `_doTransferIn` for the minter and the mintAmount.\n * `_doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n uint256 actualMintAmount = _doTransferIn(payer, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n uint256 mintTokens = div_(actualMintAmount, exchangeRate);\n\n /*\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n }\n\n /**\n * @notice User redeems vTokens in exchange for the underlying asset\n * @dev Assumes interest has already been accrued up to the current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n */\n function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\n\n /* If redeemTokensIn > 0: */\n if (redeemTokensIn > 0) {\n /*\n * We calculate the exchange rate and the amount of underlying to be redeemed:\n * redeemTokens = redeemTokensIn\n */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the redeemer and the redeemAmount.\n * On success, the vToken has redeemAmount less of cash.\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n _doTransferOut(redeemer, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n }\n\n /**\n * @notice Users borrow assets from the protocol to their own address\n * @param borrower User who borrows the assets\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the borrower and the borrowAmount.\n * On success, the vToken borrowAmount less of cash.\n * _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n _doTransferOut(borrower, borrowAmount);\n\n /* We emit a Borrow event */\n emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\n }\n\n /**\n * @notice Borrows are repaid by another user (possibly the borrower).\n * @param payer the account paying off the borrow\n * @param borrower the account with the debt being payed off\n * @param repayAmount the amount of underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : repayAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call _doTransferIn for the payer and the repayAmount\n * On success, the vToken holds an additional repayAmount of cash.\n * _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\n\n /*\n * We calculate the new borrower and total borrow balances, failing on underflow:\n * accountBorrowsNew = accountBorrows - actualRepayAmount\n * totalBorrowsNew = totalBorrows - actualRepayAmount\n */\n uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n // _liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != _getBlockNumber()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n if (vTokenCollateral.accrualBlockNumber() != _getBlockNumber()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == NO_ERROR, \"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\");\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"LIQUIDATE_SEIZE_TOO_MUCH\");\n\n // If this is also the collateral, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another VToken.\n * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\n\n /*\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\n */\n uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\n ComptrollerInterface oldComptroller = comptroller;\n // Ensure invoke comptroller.isComptroller() returns true\n require(newComptroller.isComptroller(), \"marker method returned false\");\n\n // Set market's comptroller to newComptroller\n comptroller = newComptroller;\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(oldComptroller, newComptroller);\n }\n\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n }\n\n /**\n * @notice Add reserves by transferring from caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n if (reduceAmount == 0) {\n return;\n }\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n totalReservesNew = totalReserves - reduceAmount;\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != _getBlockNumber()) {\n revert SetInterestRateModelFreshCheck();\n }\n\n // Track the market's current interest rate model\n oldInterestRateModel = interestRateModel;\n\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\n require(newInterestRateModel.isInterestRateModel(), \"marker method returned false\");\n\n // Set the interest rate model to newInterestRateModel\n interestRateModel = newInterestRateModel;\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\n }\n\n /**\n * Safe Token **\n */\n\n /**\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n * @param from Sender of the underlying tokens\n * @param amount Amount of underlying to transfer\n * @return Actual amount received\n */\n function _doTransferIn(address from, uint256 amount) internal virtual returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n // Return the amount that was *actually* transferred\n return balanceAfter - balanceBefore;\n }\n\n /**\n * @dev Just a regular ERC-20 transfer, reverts on failure\n * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\n * @dev Called by both `transfer` and `transferFrom` internally\n * @param spender The address of the account performing the transfer\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param tokens The number of tokens to transfer\n */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\n if (spender == src) {\n startingAllowance = type(uint256).max;\n } else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under,over}flow */\n uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if necessary) */\n if (startingAllowance != type(uint256).max) {\n transferAllowances[src][spender] = allowanceNew;\n }\n\n /* We emit a Transfer event */\n emit Transfer(src, dst, tokens);\n }\n\n /**\n * @notice Initialize the money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n require(accrualBlockNumber == 0 && borrowIndex == 0, \"market may only be initialized once\");\n\n // Set initial exchange rate\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa > 0, \"initial exchange rate must be greater than zero.\");\n\n _setComptroller(comptroller_);\n\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\n accrualBlockNumber = _getBlockNumber();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on block number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying tokens owned by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n return IERC20Upgradeable(underlying).balanceOf(address(this));\n }\n\n /**\n * @dev Function to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n * @return Current block number\n */\n function _getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory borrowSnapshot = accountBorrows[account];\n\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\n */\n if (borrowSnapshot.principal == 0) {\n return 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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 { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\n */\n struct BorrowSnapshot {\n uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\n\n /**\n * @notice EIP-20 token name for this token\n */\n string public name;\n\n /**\n * @notice EIP-20 token symbol for this token\n */\n string public symbol;\n\n /**\n * @notice EIP-20 token decimals for this token\n */\n uint8 public decimals;\n\n /**\n * @notice Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\n\n // Maximum borrow rate that can ever be applied (.0005% / block)\n uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16;\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n /**\n * @notice Contract which oversees inter-vToken operations\n */\n ComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\n InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\n\n /**\n * @notice delta block after which reserves will be reduced\n */\n uint256 public reduceReservesBlockDelta;\n\n /**\n * @notice last block number at which reserves were reduced\n */\n uint256 public reduceReservesBlockNumber;\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[48] private __gap;\n}\n\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the spread reserves are reduced\n */\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /**\n * @notice Event emitted when reduce reserves block delta is changed\n */\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\n\n /**\n * @notice Event emitted when liquidation reserves are reduced\n */\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/WhitePaperInterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.13;\n\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { EXP_SCALE, MANTISSA_ONE } from \"./lib/constants.sol\";\n\n/**\n * @title Compound's WhitePaperInterestRateModel Contract\n * @author Compound\n * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper\n */\ncontract WhitePaperInterestRateModel is InterestRateModel {\n /**\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\n */\n uint256 public immutable blocksPerYear;\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public immutable multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public immutable baseRatePerBlock;\n\n event NewInterestParams(uint256 baseRatePerBlock, uint256 multiplierPerBlock);\n\n /**\n * @notice Construct an interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by EXP_SCALE)\n */\n constructor(uint256 blocksPerYear_, uint256 baseRatePerYear, uint256 multiplierPerYear) {\n require(blocksPerYear_ != 0, \"Invalid blocks per year\");\n baseRatePerBlock = baseRatePerYear / blocksPerYear_;\n multiplierPerBlock = multiplierPerYear / blocksPerYear_;\n blocksPerYear = blocksPerYear_;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock);\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public view override returns (uint256) {\n uint256 ur = utilizationRate(cash, borrows, reserves, badDebt);\n return ((ur * multiplierPerBlock) / EXP_SCALE) + baseRatePerBlock;\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per block as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) public view override returns (uint256) {\n uint256 oneMinusReserveFactor = MANTISSA_ONE - reserveFactorMantissa;\n uint256 borrowRate = getBorrowRate(cash, borrows, reserves, badDebt);\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\n uint256 incomeToDistribute = borrows * rateToPool;\n uint256 supply = cash + borrows + badDebt - reserves;\n return incomeToDistribute / supply;\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `(borrows + badDebt) / (cash + borrows + badDebt - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @param badDebt The amount of badDebt in the market\n * @return The utilization rate as a mantissa between [0, MANTISSA_ONE]\n */\n function utilizationRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows and badDebt\n if ((borrows + badDebt) == 0) {\n return 0;\n }\n\n uint256 rate = ((borrows + badDebt) * EXP_SCALE) / (cash + borrows + badDebt - reserves);\n\n if (rate > EXP_SCALE) {\n rate = EXP_SCALE;\n }\n\n return rate;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/hardhat.config.ts b/hardhat.config.ts index d310b470e..a691fbfb4 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -158,22 +158,39 @@ const config: HardhatUserConfig = { live: false, }, bsctestnet: { - url: "https://bsc-testnet.public.blastapi.io", + url: process.env.ARCHIVE_NODE_bsctestnet || "https://data-seed-prebsc-1-s1.binance.org:8545", chainId: 97, live: true, gasPrice: 20000000000, - accounts: { - mnemonic: process.env.MNEMONIC || "", - }, + isTimeBased: false, + accounts: process.env.DEPLOYER_PRIVATE_KEY ? [`0x${process.env.DEPLOYER_PRIVATE_KEY}`] : [], }, + // Mainnet deployments are done through Frame wallet RPC bscmainnet: { - url: "https://bsc-dataseed.binance.org/", + url: process.env.ARCHIVE_NODE_bscmainnet || "https://bsc-dataseed.binance.org/", chainId: 56, timeout: 1200000, + isTimeBased: false, accounts: { mnemonic: process.env.MNEMONIC || "", }, }, + sepolia: { + url: process.env.ARCHIVE_NODE_sepolia || "https://ethereum-sepolia.blockpi.network/v1/rpc/public", + chainId: 11155111, + live: true, + timeout: 1200000, // 20 minutes, + isTimeBased: false, + accounts: process.env.DEPLOYER_PRIVATE_KEY ? [`0x${process.env.DEPLOYER_PRIVATE_KEY}`] : [], + }, + ethereum: { + url: process.env.ARCHIVE_NODE_ethereum || "https://ethereum.blockpi.network/v1/rpc/public", + chainId: 1, + live: true, + timeout: 1200000, // 20 minutes, + isTimeBased: false, + accounts: process.env.DEPLOYER_PRIVATE_KEY ? [`0x${process.env.DEPLOYER_PRIVATE_KEY}`] : [], + }, }, gasReporter: { enabled: process.env.REPORT_GAS !== undefined, @@ -197,10 +214,28 @@ const config: HardhatUserConfig = { browserURL: "https://bscscan.com", }, }, + { + network: "sepolia", + chainId: 11155111, + urls: { + apiURL: "https://api-sepolia.etherscan.io/api", + browserURL: "https://sepolia.etherscan.io", + }, + }, + { + network: "ethereum", + chainId: 1, + urls: { + apiURL: "https://api.etherscan.io/api", + browserURL: "https://etherscan.io", + }, + }, ], apiKey: { bscmainnet: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY", testnet: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY", + sepolia: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY", + ethereum: process.env.ETHERSCAN_API_KEY || "ETHERSCAN_API_KEY", }, }, paths: { @@ -232,19 +267,28 @@ const config: HardhatUserConfig = { bsctestnet: [ "node_modules/@venusprotocol/oracle/deployments/bsctestnet", "node_modules/@venusprotocol/venus-protocol/deployments/bsctestnet", + "node_modules/@venusprotocol/protocol-reserve/deployments/bsctestnet", ], + sepolia: [ + "node_modules/@venusprotocol/oracle/deployments/sepolia", + "node_modules/@venusprotocol/venus-protocol/deployments/sepolia", + "node_modules/@venusprotocol/protocol-reserve/deployments/sepolia", + ], + bscmainnet: ["node_modules/@venusprotocol/protocol-reserve/deployments/bscmainnet"], }, }, }; function isFork() { - return process.env.FORK_MAINNET === "true" + return process.env.FORK === "true" ? { allowUnlimitedContractSize: false, loggingEnabled: false, forking: { - url: `https://white-ultra-silence.bsc.discover.quiknode.pro/${process.env.QUICK_NODE_KEY}/`, - blockNumber: 21068448, + url: + process.env[`ARCHIVE_NODE_${process.env.FORKED_NETWORK}`] || + "https://data-seed-prebsc-1-s1.binance.org:8545", + blockNumber: 26349263, }, accounts: { accountsBalance: "1000000000000000000", @@ -255,7 +299,7 @@ function isFork() { allowUnlimitedContractSize: true, loggingEnabled: false, live: false, + isTimeBased: false, }; } - export default config; diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 14efb4c68..54fd9938f 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -1,3 +1,11 @@ +import { contracts as governanceBscMainnet } from "@venusprotocol/governance-contracts/deployments/bscmainnet.json"; +import { contracts as governanceBscTestnet } from "@venusprotocol/governance-contracts/deployments/bsctestnet.json"; +import { contracts as governanceEthereum } from "@venusprotocol/governance-contracts/deployments/ethereum.json"; +import { contracts as governanceSepolia } from "@venusprotocol/governance-contracts/deployments/sepolia.json"; +import { contracts as venusProtocolBscMainnet } from "@venusprotocol/venus-protocol/deployments/bscmainnet.json"; +import { contracts as venusProtocolBscTestnet } from "@venusprotocol/venus-protocol/deployments/bsctestnet.json"; +import { contracts as venusProtocolEthereum } from "@venusprotocol/venus-protocol/deployments/ethereum.json"; +import { contracts as venusProtocolSepolia } from "@venusprotocol/venus-protocol/deployments/sepolia.json"; import { ethers } from "hardhat"; import { DeploymentsExtension } from "hardhat-deploy/types"; @@ -7,6 +15,8 @@ export type NetworkConfig = { hardhat: DeploymentConfig; bsctestnet: DeploymentConfig; bscmainnet: DeploymentConfig; + sepolia: DeploymentConfig; + ethereum: DeploymentConfig; }; export type PreconfiguredAddresses = { [contract: string]: string }; @@ -18,6 +28,11 @@ export type DeploymentConfig = { preconfiguredAddresses: PreconfiguredAddresses; }; +export type DeploymentInfo = { + isTimeBased: boolean; + blocksPerYear: number; +}; + export type TokenConfig = { isMock: boolean; name?: string; @@ -82,40 +97,75 @@ export enum InterestRateModels { const ANY_CONTRACT = ethers.constants.AddressZero; +export const BSC_BLOCKS_PER_YEAR = 10_512_000; // assuming a block is mined every 3 seconds +export const ETH_BLOCKS_PER_YEAR = 2_252_571; // assuming a block is mined every 14 seconds +export const SECONDS_PER_YEAR = 31_536_000; // seconds per year + +export type BlocksPerYear = { + [key: string]: number; +}; + +export const blocksPerYear: BlocksPerYear = { + hardhat: BSC_BLOCKS_PER_YEAR, + bsctestnet: BSC_BLOCKS_PER_YEAR, + bscmainnet: BSC_BLOCKS_PER_YEAR, + sepolia: ETH_BLOCKS_PER_YEAR, + ethereum: ETH_BLOCKS_PER_YEAR, + isTimeBased: SECONDS_PER_YEAR, +}; + +export const SEPOLIA_MULTISIG = "0x94fa6078b6b8a26f0b6edffbe6501b22a10470fb"; +export const ETHEREUM_MULTISIG = "0x285960C5B22fD66A736C7136967A3eB15e93CC67"; + +const DEFAULT_REDUCE_RESERVES_BLOCK_DELTA = "6171"; const preconfiguredAddresses = { hardhat: { VTreasury: "account:deployer", }, bsctestnet: { - VTreasury: "0x8b293600C50D6fbdc6Ed4251cc75ECe29880276f", - NormalTimelock: "0xce10739590001705F7FF231611ba4A48B2820327", - FastTrackTimelock: "0x3CFf21b7AF8390fE68799D58727d3b4C25a83cb6", - CriticalTimelock: "0x23B893a7C45a5Eb8c8C062b9F32d0D2e43eD286D", - GovernorBravo: "0x5573422A1a59385C247ec3a66B93B7C08eC2f8f2", - AccessControlManager: "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA", - PancakeFactory: "0x182859893230dC89b114d6e2D547BFFE30474a21", - WBNB: "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", - VBNB_CorePool: "0x2E7222e51c0f6e98610A1543Aa3836E092CDe62c", - SwapRouter_CorePool: "0x83edf1deE1B730b7e8e13C00ba76027D63a51ac0", - Unitroller: "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D", - ProtocolShareReserve: "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + VTreasury: venusProtocolBscTestnet.VTreasury.address, + NormalTimelock: governanceBscTestnet.NormalTimelock.address, + FastTrackTimelock: governanceBscTestnet.FastTrackTimelock.address, + CriticalTimelock: governanceBscTestnet.CriticalTimelock.address, + GovernorBravo: governanceBscTestnet.GovernorBravoDelegator.address, + AccessControlManager: governanceBscTestnet.AccessControlManager.address, + PancakeFactory: venusProtocolBscTestnet.pancakeFactory.address, + WBNB: venusProtocolBscTestnet.WBNB.address, + VBNB_CorePool: venusProtocolBscTestnet.vBNB.address, + SwapRouter_CorePool: venusProtocolBscTestnet.SwapRouterCorePool.address, + Unitroller: venusProtocolBscTestnet.Unitroller.address, Shortfall: "0x503574a82fE2A9f968d355C8AAc1Ba0481859369", }, bscmainnet: { - VTreasury: "0xF322942f644A996A617BD29c16bd7d231d9F35E9", - NormalTimelock: "0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396", - FastTrackTimelock: "0x555ba73dB1b006F3f2C7dB7126d6e4343aDBce02", - CriticalTimelock: "0x213c446ec11e45b15a6E29C1C1b402B8897f606d", - GovernorBravo: "0x2d56dC077072B53571b8252008C60e945108c75a", - AccessControlManager: "0x4788629ABc6cFCA10F9f969efdEAa1cF70c23555", - PancakeFactory: "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73", - WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", - VBNB_CorePool: "0xA07c5b74C9B40447a954e1466938b865b6BBea36", - SwapRouter_CorePool: "0x8938E6dA30b59c1E27d5f70a94688A89F7c815a4", - Unitroller: "0xfD36E2c2a6789Db23113685031d7F16329158384", - ProtocolShareReserve: "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + VTreasury: venusProtocolBscMainnet.VTreasury.address, + NormalTimelock: governanceBscMainnet.NormalTimelock.address, + FastTrackTimelock: governanceBscMainnet.FastTrackTimelock.address, + CriticalTimelock: governanceBscMainnet.CriticalTimelock.address, + GovernorBravo: governanceBscMainnet.GovernorBravoDelegator.address, + AccessControlManager: governanceBscMainnet.AccessControlManager.address, + PancakeFactory: venusProtocolBscMainnet.pancakeFactory.address, + WBNB: venusProtocolBscMainnet.WBNB.address, + VBNB_CorePool: venusProtocolBscMainnet.vBNB.address, + SwapRouter_CorePool: venusProtocolBscMainnet.SwapRouterCorePool.address, + Unitroller: venusProtocolBscMainnet.Unitroller.address, Shortfall: "0xf37530A8a810Fcb501AA0Ecd0B0699388F0F2209", }, + sepolia: { + VTreasury: venusProtocolSepolia.VTreasuryV8.address, + NormalTimelock: SEPOLIA_MULTISIG, + FastTrackTimelock: SEPOLIA_MULTISIG, + CriticalTimelock: SEPOLIA_MULTISIG, + GovernorBravo: SEPOLIA_MULTISIG, + AccessControlManager: governanceSepolia.AccessControlManager.address, + }, + ethereum: { + VTreasury: venusProtocolEthereum.VTreasuryV8.address, + NormalTimelock: ETHEREUM_MULTISIG, + FastTrackTimelock: ETHEREUM_MULTISIG, + CriticalTimelock: ETHEREUM_MULTISIG, + GovernorBravo: ETHEREUM_MULTISIG, + AccessControlManager: governanceEthereum.AccessControlManager.address, + }, }; const poolRegistryPermissions = (): AccessControlEntry[] => { @@ -153,6 +203,7 @@ const deployerPermissions = (): AccessControlEntry[] => { const normalTimelockPermissions = (timelock: string): AccessControlEntry[] => { const methods = [ "setCloseFactor(uint256)", + "setReduceReservesBlockDelta(uint256)", "setCollateralFactor(address,uint256,uint256)", "setLiquidationIncentive(uint256)", "setMarketBorrowCaps(address[],uint256[])", @@ -167,6 +218,7 @@ const normalTimelockPermissions = (timelock: string): AccessControlEntry[] => { "setReserveFactor(uint256)", "setInterestRateModel(address)", "setRewardTokenSpeeds(address[],uint256[],uint256[])", + "setLastRewardingBlock(address[],uint32[],uint32[])", "updateJumpRateModel(uint256,uint256,uint256,uint256)", ]; return methods.map(method => ({ @@ -311,7 +363,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(932019, 18), borrowCap: convertToUnit(478980, 18), vTokenReceiver: "account:deployer", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus BTCB", @@ -329,7 +381,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(1000, 18), borrowCap: convertToUnit(1000, 18), vTokenReceiver: "account:deployer", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, ], rewards: [ @@ -370,7 +422,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(3000000, 18), borrowCap: convertToUnit(3000000, 18), vTokenReceiver: "account:deployer", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus ankrBNB", @@ -388,7 +440,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(100, 18), borrowCap: convertToUnit(100, 18), vTokenReceiver: "account:deployer", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus MBOX", @@ -406,7 +458,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(7000000, 18), borrowCap: convertToUnit(3184294, 18), vTokenReceiver: "account:deployer", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus NFT", @@ -424,7 +476,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(84985800573, 18), borrowCap: convertToUnit(24654278679, 18), vTokenReceiver: "account:deployer", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus RACA", @@ -442,7 +494,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(23758811062, 18), borrowCap: convertToUnit(3805812642, 18), vTokenReceiver: "account:deployer", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus stkBNB", @@ -460,7 +512,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(1963, 18), borrowCap: convertToUnit(324, 18), vTokenReceiver: "account:deployer", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDD", @@ -478,7 +530,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(10601805, 18), borrowCap: convertToUnit(1698253, 18), vTokenReceiver: "account:deployer", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, ], rewards: [ @@ -698,6 +750,13 @@ export const globalConfig: NetworkConfig = { decimals: 18, tokenAddress: "0xd2aF6A916Bc77764dc63742BC30f71AF4cF423F4", }, + { + isMock: false, + name: "PLANET", + symbol: "PLANET", + decimals: 18, + tokenAddress: "0x52b4E1A2ba407813F829B4b3943A1e57768669A9", + }, ], poolConfig: [ { @@ -723,7 +782,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(500_000, 18), borrowCap: convertToUnit(200_000, 18), vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDT (Stable Coins)", @@ -741,7 +800,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(1_000_000, 6), // USDT has 6 decimals on testnet borrowCap: convertToUnit(400_000, 6), // USDT has 6 decimals on testnet vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDD (Stable Coins)", @@ -759,7 +818,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(1_000_000, 18), borrowCap: convertToUnit(400_000, 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus agEUR (Stablecoins)", @@ -777,7 +836,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(100000, 18), borrowCap: convertToUnit(50000, 18), vTokenReceiver: "0xc444949e0054a23c44fc45789738bdf64aed2391", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, ], rewards: [ @@ -824,7 +883,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("15000000", 18), borrowCap: convertToUnit("10500000", 18), vTokenReceiver: "0x109E8083a64c7DedE513e8b580c5b08B96f9cE73", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus ALPACA (DeFi)", @@ -842,7 +901,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2500000", 18), borrowCap: convertToUnit("1750000", 18), vTokenReceiver: "0xAD9CADe20100B8b945da48e1bCbd805C38d8bE77", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDT (DeFi)", @@ -860,7 +919,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("18600000", 6), // USDT has 6 decimals on testnet borrowCap: convertToUnit("14880000", 6), // USDT has 6 decimals on testnet vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDD (DeFi)", @@ -878,7 +937,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2000000", 18), borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus ANKR (DeFi)", @@ -896,7 +955,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("9508802", 18), borrowCap: convertToUnit("6656161", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus ankrBNB (DeFi)", @@ -914,7 +973,25 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("5000", 18), borrowCap: convertToUnit("4000", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", + }, + { + name: "Venus PLANET (DeFi)", + asset: "PLANET", + symbol: "vPLANET_DeFi", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.2", 18), + jumpMultiplierPerYear: convertToUnit("3", 18), + kink_: convertToUnit("0.45", 18), + collateralFactor: convertToUnit("0.2", 18), + liquidationThreshold: convertToUnit("0.3", 18), + reserveFactor: convertToUnit("0.25", 18), + initialSupply: convertToUnit("174983000", 18), + supplyCap: convertToUnit("1000000000", 18), + borrowCap: convertToUnit("500000000", 18), + vTokenReceiver: "0x0554d6079eBc222AD12405E52b264Bdb5B65D1cf", + reduceReservesBlockDelta: "100", }, ], rewards: [ @@ -930,6 +1007,12 @@ export const globalConfig: NetworkConfig = { supplySpeeds: ["289351851851851851"], // 250000 ANKR over 30 days (864000 blocks) borrowSpeeds: ["289351851851851851"], // 250000 ANKR over 30 days (864000 blocks) }, + { + asset: "USDT", + markets: ["PLANET"], + supplySpeeds: ["1860"], // 1500 USDT over 28 days (806400 blocks) + borrowSpeeds: ["1860"], // 1500 USDT over 28 days (806400 blocks) + }, ], }, { @@ -955,7 +1038,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("4000000000", 18), borrowCap: convertToUnit("2800000000", 18), vTokenReceiver: "0x6Ee74536B3Ff10Ff639aa781B7220121287F6Fa5", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus FLOKI (GameFi)", @@ -973,7 +1056,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("40000000000", 18), // FLOKI has 18 decimals on testnet borrowCap: convertToUnit("28000000000", 18), // FLOKI has 18 decimals on testnet vTokenReceiver: "0x17e98a24f992BB7bcd62d6722d714A3C74814B94", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDT (GameFi)", @@ -991,7 +1074,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("18600000", 6), // USDT has 6 decimals on testnet borrowCap: convertToUnit("14880000", 6), // USDT has 6 decimals on testnet vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDD (GameFi)", @@ -1009,7 +1092,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2000000", 18), borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, ], rewards: [ @@ -1050,7 +1133,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("8000", 18), borrowCap: convertToUnit("5600", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus BNBx (Liquid Staked BNB)", @@ -1068,7 +1151,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("1818", 18), borrowCap: convertToUnit("1272", 18), vTokenReceiver: "0xF0348E1748FCD45020151C097D234DbbD5730BE7", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus stkBNB (Liquid Staked BNB)", @@ -1086,7 +1169,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("540", 18), borrowCap: convertToUnit("378", 18), vTokenReceiver: "0xccc022502d6c65e1166fd34147040f05880f7972", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus WBNB (Liquid Staked BNB)", @@ -1104,7 +1187,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("80000", 18), borrowCap: convertToUnit("56000", 18), vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDT (Liquid Staked BNB)", @@ -1122,7 +1205,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("18600000", 6), // USDT has 6 decimals on testnet borrowCap: convertToUnit("14880000", 6), // USDT has 6 decimals on testnet vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDD (Liquid Staked BNB)", @@ -1140,7 +1223,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2000000", 18), borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus SnBNB (Liquid Staked BNB)", @@ -1158,7 +1241,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("1000", 18), borrowCap: convertToUnit("100", 18), vTokenReceiver: "0xDC2D855A95Ee70d7282BebD35c96f905CDE31f55", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, ], rewards: [ @@ -1217,7 +1300,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("1500000000000", 18), borrowCap: convertToUnit("1050000000000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus NFT (Tron)", @@ -1235,7 +1318,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("4000000000", 18), // NFT has 18 decimals on testnet borrowCap: convertToUnit("2800000000", 18), // NFT has 18 decimals on testnet vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus WIN (Tron)", @@ -1253,7 +1336,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("3000000000", 18), borrowCap: convertToUnit("2100000000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus TRX (Tron)", @@ -1271,7 +1354,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("11000000", 6), // Note 6 decimals borrowCap: convertToUnit("7700000", 6), // Note 6 decimals vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDT (Tron)", @@ -1289,7 +1372,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("18600000", 6), // USDT has 6 decimals on testnet borrowCap: convertToUnit("14880000", 6), // USDT has 6 decimals on testnet vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, { name: "Venus USDD (Tron)", @@ -1307,7 +1390,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2000000", 18), borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "100", }, ], rewards: [ @@ -1495,6 +1578,13 @@ export const globalConfig: NetworkConfig = { decimals: 18, tokenAddress: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B", }, + { + isMock: false, + name: "PLANET", + symbol: "PLANET", + decimals: 18, + tokenAddress: "0xca6d678e74f553f0e59cccc03ae644a3c2c5ee7d", + }, ], poolConfig: [ { @@ -1520,7 +1610,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(500_000, 18), borrowCap: convertToUnit(200_000, 18), vTokenReceiver: "0x09702Ea135d9D707DD51f530864f2B9220aAD87B", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDT (Stablecoins)", @@ -1538,7 +1628,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(1_000_000, 18), borrowCap: convertToUnit(400_000, 18), vTokenReceiver: "0xF322942f644A996A617BD29c16bd7d231d9F35E9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDD (Stablecoins)", @@ -1556,7 +1646,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(1_000_000, 18), borrowCap: convertToUnit(400_000, 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus agEUR (Stablecoins)", @@ -1574,7 +1664,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit(100000, 18), borrowCap: convertToUnit(50000, 18), vTokenReceiver: "0xc444949e0054a23c44fc45789738bdf64aed2391", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, ], rewards: [ @@ -1621,7 +1711,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("15000000", 18), borrowCap: convertToUnit("10500000", 18), vTokenReceiver: "0x109E8083a64c7DedE513e8b580c5b08B96f9cE73", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus ALPACA (DeFi)", @@ -1639,7 +1729,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2500000", 18), borrowCap: convertToUnit("1750000", 18), vTokenReceiver: "0xAD9CADe20100B8b945da48e1bCbd805C38d8bE77", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDT (DeFi)", @@ -1657,7 +1747,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("18600000", 18), borrowCap: convertToUnit("14880000", 18), vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDD (DeFi)", @@ -1675,7 +1765,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2000000", 18), borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus ANKR (DeFi)", @@ -1693,7 +1783,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("9508802", 18), borrowCap: convertToUnit("6656161", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { @@ -1712,7 +1802,25 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("5000", 18), borrowCap: convertToUnit("4000", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", + }, + { + name: "Venus PLANET (DeFi)", + asset: "PLANET", + symbol: "vPLANET_DeFi", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.2", 18), + jumpMultiplierPerYear: convertToUnit("3", 18), + kink_: convertToUnit("0.45", 18), + collateralFactor: convertToUnit("0.2", 18), + liquidationThreshold: convertToUnit("0.3", 18), + reserveFactor: convertToUnit("0.25", 18), + initialSupply: convertToUnit("174983000", 18), + supplyCap: convertToUnit("1000000000", 18), + borrowCap: convertToUnit("500000000", 18), + vTokenReceiver: "0x0554d6079eBc222AD12405E52b264Bdb5B65D1cf", + reduceReservesBlockDelta: "28800", }, ], rewards: [ @@ -1729,6 +1837,12 @@ export const globalConfig: NetworkConfig = { supplySpeeds: ["289351851851851851"], // 250000 ANKR over 30 days (864000 blocks) borrowSpeeds: ["289351851851851851"], // 250000 ANKR over 30 days (864000 blocks) }, + { + asset: "USDT", + markets: ["PLANET"], + supplySpeeds: ["1860119047619047"], // 1500 USDT over 28 days (806400 blocks) + borrowSpeeds: ["1860119047619047"], // 1500 USDT over 28 days (806400 blocks) + }, ], }, { @@ -1754,7 +1868,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("4000000000", 18), borrowCap: convertToUnit("2800000000", 18), vTokenReceiver: "0x6Ee74536B3Ff10Ff639aa781B7220121287F6Fa5", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus FLOKI (GameFi)", @@ -1772,7 +1886,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("40000000000", 9), // Note 9 decimals borrowCap: convertToUnit("28000000000", 9), // Note 9 decimals vTokenReceiver: "0x17e98a24f992BB7bcd62d6722d714A3C74814B94", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDT (GameFi)", @@ -1790,7 +1904,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("18600000", 18), borrowCap: convertToUnit("14880000", 18), vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDD (GameFi)", @@ -1808,7 +1922,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2000000", 18), borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, ], rewards: [ @@ -1849,7 +1963,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("8000", 18), borrowCap: convertToUnit("5600", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus BNBx (Liquid Staked BNB)", @@ -1867,7 +1981,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("1818", 18), borrowCap: convertToUnit("1272", 18), vTokenReceiver: "0xF0348E1748FCD45020151C097D234DbbD5730BE7", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus stkBNB (Liquid Staked BNB)", @@ -1885,7 +1999,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("540", 18), borrowCap: convertToUnit("378", 18), vTokenReceiver: "0xccc022502d6c65e1166fd34147040f05880f7972", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus WBNB (Liquid Staked BNB)", @@ -1903,7 +2017,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("80000", 18), borrowCap: convertToUnit("56000", 18), vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDT (Liquid Staked BNB)", @@ -1921,7 +2035,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("18600000", 18), borrowCap: convertToUnit("14880000", 18), vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDD (Liquid Staked BNB)", @@ -1939,7 +2053,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2000000", 18), borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus SnBNB (Liquid Staked BNB)", @@ -1957,7 +2071,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("1000", 18), borrowCap: convertToUnit("100", 18), vTokenReceiver: "0xDC2D855A95Ee70d7282BebD35c96f905CDE31f55", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, ], rewards: [ @@ -2016,7 +2130,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("1500000000000", 18), borrowCap: convertToUnit("1050000000000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus NFT (Tron)", @@ -2034,7 +2148,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("4000000000", 6), // Note 6 decimals borrowCap: convertToUnit("2800000000", 6), // Note 6 decimals vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus WIN (Tron)", @@ -2052,7 +2166,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("3000000000", 18), borrowCap: convertToUnit("2100000000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus TRX (Tron)", @@ -2070,7 +2184,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("11000000", 6), // Note 6 decimals borrowCap: convertToUnit("7700000", 6), // Note 6 decimals vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDT (Tron)", @@ -2088,7 +2202,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("18600000", 18), borrowCap: convertToUnit("14880000", 18), vTokenReceiver: "0xf322942f644a996a617bd29c16bd7d231d9f35e9", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, { name: "Venus USDD (Tron)", @@ -2106,7 +2220,7 @@ export const globalConfig: NetworkConfig = { supplyCap: convertToUnit("2000000", 18), borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", - reduceReservesBlockDelta: "10512000", + reduceReservesBlockDelta: "28800", }, ], rewards: [ @@ -2145,6 +2259,582 @@ export const globalConfig: NetworkConfig = { ], preconfiguredAddresses: preconfiguredAddresses.bscmainnet, }, + sepolia: { + tokensConfig: [ + { + isMock: true, + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + tokenAddress: ethers.constants.AddressZero, + }, + { + isMock: true, + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + tokenAddress: ethers.constants.AddressZero, + }, + { + isMock: true, + name: "Tether USD", + symbol: "USDT", + decimals: 6, + tokenAddress: ethers.constants.AddressZero, + }, + { + isMock: true, + name: "USD Coin", + symbol: "USDC", + decimals: 6, + tokenAddress: ethers.constants.AddressZero, + }, + { + isMock: false, + name: "Venus", + symbol: "XVS", + decimals: 18, + tokenAddress: "0xdb633c11d3f9e6b8d17ac2c972c9e3b05da59bf9", + }, + { + isMock: true, + name: "Curve DAO Token", + symbol: "CRV", + decimals: 18, + tokenAddress: ethers.constants.AddressZero, + }, + { + isMock: true, + name: "Curve.Fi USD Stablecoin", + symbol: "crvUSD", + decimals: 18, + tokenAddress: ethers.constants.AddressZero, + }, + ], + poolConfig: [ + { + id: "Core", + name: "Core", + closeFactor: convertToUnit("0.5", 18), + liquidationIncentive: convertToUnit("1.1", 18), + minLiquidatableCollateral: convertToUnit("100", 18), + vtokens: [ + { + name: "Venus WBTC (Core)", + asset: "WBTC", + symbol: "vWBTC_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.05", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.75", 18), + collateralFactor: convertToUnit("0.75", 18), + liquidationThreshold: convertToUnit("0.8", 18), + reserveFactor: convertToUnit("0.2", 18), + initialSupply: convertToUnit("0.3", 8), // 0.3 WBTC + supplyCap: convertToUnit(300, 8), + borrowCap: convertToUnit(250, 8), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + { + name: "Venus WETH (Core)", + asset: "WETH", + symbol: "vWETH_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.045", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.75", 18), + liquidationThreshold: convertToUnit("0.8", 18), + reserveFactor: convertToUnit("0.2", 18), + initialSupply: convertToUnit(5, 18), // 5 WETH + supplyCap: convertToUnit(5500, 18), + borrowCap: convertToUnit(4600, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + { + name: "Venus USDC (Core)", + asset: "USDC", + symbol: "vUSDC_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.8", 18), + liquidationThreshold: convertToUnit("0.82", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 6), // 10,000 USDC + supplyCap: convertToUnit(10_000_000, 6), + borrowCap: convertToUnit(9_000_000, 6), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + { + name: "Venus USDT (Core)", + asset: "USDT", + symbol: "vUSDT_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.8", 18), + liquidationThreshold: convertToUnit("0.82", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 6), // 10,000 USDT + supplyCap: convertToUnit(10_000_000, 6), + borrowCap: convertToUnit(9_000_000, 6), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + { + name: "Venus crvUSD (Core)", + asset: "crvUSD", + symbol: "vcrvUSD_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.8", 18), + liquidationThreshold: convertToUnit("0.82", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 18), + supplyCap: convertToUnit(10_000_000, 18), + borrowCap: convertToUnit(9_000_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + { + name: "Venus CRV (Core)", + asset: "CRV", + symbol: "vCRV_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.15", 18), + jumpMultiplierPerYear: convertToUnit(3, 18), + kink_: convertToUnit("0.45", 18), + collateralFactor: convertToUnit("0.35", 18), + liquidationThreshold: convertToUnit("0.4", 18), + reserveFactor: convertToUnit("0.25", 18), + initialSupply: convertToUnit(20_000, 18), + supplyCap: convertToUnit(5_000_000, 18), + borrowCap: convertToUnit(2_500_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + ], + rewards: [], + }, + { + id: "Stablecoins", + name: "Stablecoins", + closeFactor: convertToUnit("0.5", 18), + liquidationIncentive: convertToUnit("1.1", 18), + minLiquidatableCollateral: convertToUnit("100", 18), + vtokens: [ + { + name: "Venus USDC (Stablecoins)", + asset: "USDC", + symbol: "vUSDC_Stablecoins", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.85", 18), + liquidationThreshold: convertToUnit("0.9", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 6), // 10,000 USDC + supplyCap: convertToUnit(5_000_000, 6), + borrowCap: convertToUnit(4_500_000, 6), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + { + name: "Venus USDT (Stablecoins)", + asset: "USDT", + symbol: "vUSDT_Stablecoins", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.85", 18), + liquidationThreshold: convertToUnit("0.9", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 6), // 10,000 USDT + supplyCap: convertToUnit(5_000_000, 6), + borrowCap: convertToUnit(4_500_000, 6), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + { + name: "Venus crvUSD (Stablecoins)", + asset: "crvUSD", + symbol: "vcrvUSD_Stablecoins", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.85", 18), + liquidationThreshold: convertToUnit("0.9", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 18), // 10,000 crvUSD + supplyCap: convertToUnit(5_000_000, 18), + borrowCap: convertToUnit(4_500_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + ], + rewards: [], + }, + { + id: "Curve", + name: "Curve", + closeFactor: convertToUnit("0.5", 18), + liquidationIncentive: convertToUnit("1.1", 18), + minLiquidatableCollateral: convertToUnit("100", 18), + vtokens: [ + { + name: "Venus crvUSD (Curve)", + asset: "crvUSD", + symbol: "vcrvUSD_Curve", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.75", 18), + liquidationThreshold: convertToUnit("0.8", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 18), + supplyCap: convertToUnit(2_500_000, 18), + borrowCap: convertToUnit(2_000_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + { + name: "Venus CRV (Curve)", + asset: "CRV", + symbol: "vCRV_Curve", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.2", 18), + jumpMultiplierPerYear: convertToUnit(3, 18), + kink_: convertToUnit("0.45", 18), + collateralFactor: convertToUnit("0.6", 18), + liquidationThreshold: convertToUnit("0.65", 18), + reserveFactor: convertToUnit("0.25", 18), + initialSupply: convertToUnit(20_000, 18), + supplyCap: convertToUnit(5_000_000, 18), + borrowCap: convertToUnit(2_500_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + }, + ], + rewards: [], + }, + ], + accessControlConfig: [ + ...poolRegistryPermissions(), + ...normalTimelockPermissions(preconfiguredAddresses.sepolia.NormalTimelock), + ], + preconfiguredAddresses: preconfiguredAddresses.sepolia, + }, + ethereum: { + tokensConfig: [ + { + isMock: false, + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + tokenAddress: "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", + }, + { + isMock: false, + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + tokenAddress: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + }, + { + isMock: false, + name: "Tether USD", + symbol: "USDT", + decimals: 6, + tokenAddress: "0xdac17f958d2ee523a2206206994597c13d831ec7", + }, + { + isMock: false, + name: "USD Coin", + symbol: "USDC", + decimals: 6, + tokenAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + }, + { + isMock: false, + name: "Venus", + symbol: "XVS", + decimals: 18, + tokenAddress: "", // TODO: add address when XVS deployed on mainnet + }, + { + isMock: false, + name: "Curve DAO Token", + symbol: "CRV", + decimals: 18, + tokenAddress: "0xD533a949740bb3306d119CC777fa900bA034cd52", + }, + { + isMock: false, + name: "Curve.Fi USD Stablecoin", + symbol: "crvUSD", + decimals: 18, + tokenAddress: "0xf939e0a03fb07f59a73314e73794be0e57ac1b4e", + }, + ], + poolConfig: [ + { + id: "Core", + name: "Core", + closeFactor: convertToUnit("0.5", 18), + liquidationIncentive: convertToUnit("1.1", 18), + minLiquidatableCollateral: convertToUnit("100", 18), + vtokens: [ + { + name: "Venus WBTC (Core)", + asset: "WBTC", + symbol: "vWBTC_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.05", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.75", 18), + collateralFactor: convertToUnit("0.75", 18), + liquidationThreshold: convertToUnit("0.8", 18), + reserveFactor: convertToUnit("0.2", 18), + initialSupply: convertToUnit("0.3", 8), // 0.3 WBTC + supplyCap: convertToUnit(300, 8), + borrowCap: convertToUnit(250, 8), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + { + name: "Venus WETH (Core)", + asset: "WETH", + symbol: "vWETH_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.045", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.75", 18), + liquidationThreshold: convertToUnit("0.8", 18), + reserveFactor: convertToUnit("0.2", 18), + initialSupply: convertToUnit(5, 18), // 5 WETH + supplyCap: convertToUnit(5500, 18), + borrowCap: convertToUnit(4600, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + { + name: "Venus USDC (Core)", + asset: "USDC", + symbol: "vUSDC_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.8", 18), + liquidationThreshold: convertToUnit("0.82", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 6), // 10,000 USDC + supplyCap: convertToUnit(10_000_000, 6), + borrowCap: convertToUnit(9_000_000, 6), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + { + name: "Venus USDT (Core)", + asset: "USDT", + symbol: "vUSDT_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.8", 18), + liquidationThreshold: convertToUnit("0.82", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 6), // 10,000 USDT + supplyCap: convertToUnit(10_000_000, 6), + borrowCap: convertToUnit(9_000_000, 6), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + { + name: "Venus crvUSD (Core)", + asset: "crvUSD", + symbol: "vcrvUSD_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.8", 18), + liquidationThreshold: convertToUnit("0.82", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 18), + supplyCap: convertToUnit(10_000_000, 18), + borrowCap: convertToUnit(9_000_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + { + name: "Venus CRV (Core)", + asset: "CRV", + symbol: "vCRV_Core", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.15", 18), + jumpMultiplierPerYear: convertToUnit(3, 18), + kink_: convertToUnit("0.45", 18), + collateralFactor: convertToUnit("0.35", 18), + liquidationThreshold: convertToUnit("0.4", 18), + reserveFactor: convertToUnit("0.25", 18), + initialSupply: convertToUnit(20_000, 18), + supplyCap: convertToUnit(5_000_000, 18), + borrowCap: convertToUnit(2_500_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + ], + rewards: [], + }, + { + id: "Stablecoins", + name: "Stablecoins", + closeFactor: convertToUnit("0.5", 18), + liquidationIncentive: convertToUnit("1.1", 18), + minLiquidatableCollateral: convertToUnit("100", 18), + vtokens: [ + { + name: "Venus USDC (Stablecoins)", + asset: "USDC", + symbol: "vUSDC_Stablecoins", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.85", 18), + liquidationThreshold: convertToUnit("0.9", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 6), // 10,000 USDC + supplyCap: convertToUnit(5_000_000, 6), + borrowCap: convertToUnit(4_500_000, 6), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + { + name: "Venus USDT (Stablecoins)", + asset: "USDT", + symbol: "vUSDT_Stablecoins", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.85", 18), + liquidationThreshold: convertToUnit("0.9", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 6), // 10,000 USDT + supplyCap: convertToUnit(5_000_000, 6), + borrowCap: convertToUnit(4_500_000, 6), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + { + name: "Venus crvUSD (Stablecoins)", + asset: "crvUSD", + symbol: "vcrvUSD_Stablecoins", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.85", 18), + liquidationThreshold: convertToUnit("0.9", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 18), // 10,000 crvUSD + supplyCap: convertToUnit(5_000_000, 18), + borrowCap: convertToUnit(4_500_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + ], + rewards: [], + }, + { + id: "Curve", + name: "Curve", + closeFactor: convertToUnit("0.5", 18), + liquidationIncentive: convertToUnit("1.1", 18), + minLiquidatableCollateral: convertToUnit("100", 18), + vtokens: [ + { + name: "Venus crvUSD (Curve)", + asset: "crvUSD", + symbol: "vcrvUSD_Curve", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: "0", + multiplierPerYear: convertToUnit("0.07", 18), + jumpMultiplierPerYear: convertToUnit("0.8", 18), + kink_: convertToUnit("0.8", 18), + collateralFactor: convertToUnit("0.75", 18), + liquidationThreshold: convertToUnit("0.8", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10_000, 18), + supplyCap: convertToUnit(2_500_000, 18), + borrowCap: convertToUnit(2_000_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + { + name: "Venus CRV (Curve)", + asset: "CRV", + symbol: "vCRV_Curve", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.2", 18), + jumpMultiplierPerYear: convertToUnit(3, 18), + kink_: convertToUnit("0.45", 18), + collateralFactor: convertToUnit("0.6", 18), + liquidationThreshold: convertToUnit("0.65", 18), + reserveFactor: convertToUnit("0.25", 18), + initialSupply: convertToUnit(20_000, 18), + supplyCap: convertToUnit(5_000_000, 18), + borrowCap: convertToUnit(2_500_000, 18), + reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, + vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + }, + ], + rewards: [], + }, + ], + accessControlConfig: [ + ...poolRegistryPermissions(), + ...normalTimelockPermissions(preconfiguredAddresses.ethereum.NormalTimelock), + ], + preconfiguredAddresses: preconfiguredAddresses.ethereum, + }, }; export async function getConfig(networkName: string): Promise { @@ -2155,6 +2845,10 @@ export async function getConfig(networkName: string): Promise return globalConfig.bsctestnet; case "bscmainnet": return globalConfig.bscmainnet; + case "sepolia": + return globalConfig.sepolia; + case "ethereum": + return globalConfig.ethereum; case "development": return globalConfig.bsctestnet; default: diff --git a/helpers/deploymentUtils.ts b/helpers/deploymentUtils.ts index 3686e01ee..6f9c0533a 100644 --- a/helpers/deploymentUtils.ts +++ b/helpers/deploymentUtils.ts @@ -2,7 +2,15 @@ import { ethers } from "hardhat"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { Comptroller, ERC20, MockToken } from "../typechain"; -import { PoolConfig, RewardConfig, TokenConfig, VTokenConfig, getTokenConfig } from "./deploymentConfig"; +import { + DeploymentInfo, + PoolConfig, + RewardConfig, + TokenConfig, + VTokenConfig, + blocksPerYear, + getTokenConfig, +} from "./deploymentConfig"; export const toAddress = async (addressOrAlias: string, hre: HardhatRuntimeEnvironment): Promise => { const { getNamedAccounts } = hre; @@ -126,3 +134,10 @@ export const getUnregisteredRewardsDistributors = async ( }), ); }; + +export const getBlockOrTimestampBasedDeploymentInfo = (hre: any): DeploymentInfo => { + const isTimeBased = hre.network.config.isTimeBased; + const blocksPerYearKey = isTimeBased ? "isTimeBased" : hre.network.name; + + return { isTimeBased: isTimeBased, blocksPerYear: blocksPerYear[blocksPerYearKey] }; +}; diff --git a/package.json b/package.json index 998db01ca..f00286e51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/isolated-pools", - "version": "2.2.1-dev.1", + "version": "2.3.0-dev.3", "description": "", "files": [ "artifacts", @@ -69,10 +69,10 @@ "@types/node": "^12.20.50", "@typescript-eslint/eslint-plugin": "^5.27.1", "@typescript-eslint/parser": "^5.27.1", - "@venusprotocol/governance-contracts": "^1.0.0", - "@venusprotocol/oracle": "1.7.2", - "@venusprotocol/protocol-reserve": "^1.1.0-dev.1", - "@venusprotocol/venus-protocol": "3.0.0-dev.18", + "@venusprotocol/governance-contracts": "1.4.0-dev.2", + "@venusprotocol/oracle": "1.8.0-dev.3", + "@venusprotocol/protocol-reserve": "1.2.0-dev.2", + "@venusprotocol/venus-protocol": "6.0.1-dev.2", "bignumber.js": "9.0.0", "chai": "^4.3.6", "dotenv": "^10.0.0", diff --git a/tests/hardhat/Fork/RewardsForkTest.ts b/tests/hardhat/Fork/RewardsForkTest.ts index 305cbf22c..c8219674e 100644 --- a/tests/hardhat/Fork/RewardsForkTest.ts +++ b/tests/hardhat/Fork/RewardsForkTest.ts @@ -25,8 +25,8 @@ import { initMainnetUser, setForkBlock } from "./utils"; const { expect } = chai; chai.use(smock.matchers); -const FORK_TESTNET = process.env.FORK_TESTNET === "true"; -const FORK_MAINNET = process.env.FORK_MAINNET === "true"; +const FORK_TESTNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bsctestnet"; +const FORK_MAINNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bscmainnet"; const MANTISSA_ONE = convertToUnit(1, 18); let ADMIN: string; diff --git a/tests/hardhat/Fork/RiskFund.ts b/tests/hardhat/Fork/RiskFund.ts index edd1501c9..173790b83 100644 --- a/tests/hardhat/Fork/RiskFund.ts +++ b/tests/hardhat/Fork/RiskFund.ts @@ -52,7 +52,7 @@ let usdcUser: SignerWithAddress; let usdtUser: SignerWithAddress; const maxLoopsLimit = 150; -const FORK_MAINNET = process.env.FORK_MAINNET === "true"; +const FORK_MAINNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bscmainnet"; const someNonzeroAddress = "0x0000000000000000000000000000000000000001"; const initPancakeSwapRouter = async ( diff --git a/tests/hardhat/Fork/RiskFundSwap.ts b/tests/hardhat/Fork/RiskFundSwap.ts index 4fb19a3b6..b1887186d 100644 --- a/tests/hardhat/Fork/RiskFundSwap.ts +++ b/tests/hardhat/Fork/RiskFundSwap.ts @@ -39,7 +39,7 @@ let busdUser: SignerWithAddress; let usdtUser: SignerWithAddress; const maxLoopsLimit = 150; -const FORK_MAINNET = process.env.FORK_MAINNET === "true"; +const FORK_MAINNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bscmainnet"; const ADD_RESERVE_AMOUNT = parseUnits("100", 18); const REDUCE_RESERVE_AMOUNT = parseUnits("50", 18); @@ -105,11 +105,11 @@ const riskFundFixture = async (): Promise => { fakeAccessControlManager.isAllowedToCall.returns(true); const Shortfall = await ethers.getContractFactory("Shortfall"); - const shortfall = await upgrades.deployProxy(Shortfall, [ - AddressOne, - parseUnits("10000", 18), - fakeAccessControlManager.address, - ]); + const shortfall = await upgrades.deployProxy( + Shortfall, + [AddressOne, parseUnits("10000", 18), fakeAccessControlManager.address], + { constructorArgs: [false, 10512000] }, + ); const fakeCorePoolComptroller = await smock.fake("Comptroller"); diff --git a/tests/hardhat/Fork/Shortfall.ts b/tests/hardhat/Fork/Shortfall.ts index 181de7991..35f743931 100644 --- a/tests/hardhat/Fork/Shortfall.ts +++ b/tests/hardhat/Fork/Shortfall.ts @@ -29,7 +29,7 @@ import { initMainnetUser, setForkBlock } from "./utils"; const { expect } = chai; chai.use(smock.matchers); -const FORK_MAINNET = process.env.FORK_MAINNET === "true"; +const FORK_MAINNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bscmainnet"; const ADMIN = "0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396"; const TREASURY = "0xF322942f644A996A617BD29c16bd7d231d9F35E9"; diff --git a/tests/hardhat/Fork/borrowAndRepayTest.ts b/tests/hardhat/Fork/borrowAndRepayTest.ts index 7ef44fdd5..d307eb1ca 100644 --- a/tests/hardhat/Fork/borrowAndRepayTest.ts +++ b/tests/hardhat/Fork/borrowAndRepayTest.ts @@ -24,8 +24,8 @@ import { initMainnetUser, setForkBlock } from "./utils"; const { expect } = chai; chai.use(smock.matchers); -const FORK_TESTNET = process.env.FORK_TESTNET === "true"; -const FORK_MAINNET = process.env.FORK_MAINNET === "true"; +const FORK_TESTNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bsctestnet"; +const FORK_MAINNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bscmainnet"; let ADMIN: string; let ACM: string; diff --git a/tests/hardhat/Fork/liquidation.ts b/tests/hardhat/Fork/liquidation.ts index e3488e17d..c3a574aca 100644 --- a/tests/hardhat/Fork/liquidation.ts +++ b/tests/hardhat/Fork/liquidation.ts @@ -25,7 +25,7 @@ import { initMainnetUser, setForkBlock } from "./utils"; const { expect } = chai; chai.use(smock.matchers); -const FORK_TESTNET = process.env.FORK_TESTNET === "true"; +const FORK_TESTNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bsctestnet"; const ADMIN = "0xce10739590001705F7FF231611ba4A48B2820327"; const ORACLE_ADMIN = "0xce10739590001705F7FF231611ba4A48B2820327"; diff --git a/tests/hardhat/Fork/reduceReservesTest.ts b/tests/hardhat/Fork/reduceReservesTest.ts index 0c3d6f1c9..e5adc8c6f 100644 --- a/tests/hardhat/Fork/reduceReservesTest.ts +++ b/tests/hardhat/Fork/reduceReservesTest.ts @@ -21,8 +21,8 @@ import { initMainnetUser, setForkBlock } from "./utils"; const { expect } = chai; chai.use(smock.matchers); -const FORK_TESTNET = process.env.FORK_TESTNET === "true"; -const FORK_MAINNET = process.env.FORK_MAINNET === "true"; +const FORK_TESTNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bsctestnet"; +const FORK_MAINNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bscmainnet"; let ADMIN: string; let ACM: string; diff --git a/tests/hardhat/Fork/supply.ts b/tests/hardhat/Fork/supply.ts index 3d45b3127..c8f89e3f3 100644 --- a/tests/hardhat/Fork/supply.ts +++ b/tests/hardhat/Fork/supply.ts @@ -25,7 +25,7 @@ import { initMainnetUser, setForkBlock } from "./utils"; const { expect } = chai; chai.use(smock.matchers); -const FORK_TESTNET = process.env.FORK_TESTNET === "true"; +const FORK_TESTNET = process.env.FORK === "true" && process.env.FORKED_NETWORK === "bsctestnet"; const ADMIN = "0xce10739590001705f7ff231611ba4a48b2820327"; const ORACLE_ADMIN = "0xce10739590001705F7FF231611ba4A48B2820327"; diff --git a/tests/hardhat/Fork/utils.ts b/tests/hardhat/Fork/utils.ts index e6b97399d..512f460d9 100644 --- a/tests/hardhat/Fork/utils.ts +++ b/tests/hardhat/Fork/utils.ts @@ -17,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}`], blockNumber: blockNumber, }, }, diff --git a/tests/hardhat/JumpRateModelV2.ts b/tests/hardhat/JumpRateModelV2.ts index f80f2dd93..3db11c278 100644 --- a/tests/hardhat/JumpRateModelV2.ts +++ b/tests/hardhat/JumpRateModelV2.ts @@ -4,13 +4,15 @@ import BigNumber from "bignumber.js"; import chai from "chai"; import { ethers } from "hardhat"; +import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; import { convertToUnit } from "../../helpers/utils"; import { AccessControlManager, JumpRateModelV2 } from "../../typechain"; +import { getDescription } from "./util/descriptionHelpers"; const { expect } = chai; chai.use(smock.matchers); -describe("Jump rate model tests", () => { +for (const isTimeBased of [false, true]) { let jumpRateModel: JumpRateModelV2; let accessControlManager: FakeContract; @@ -20,107 +22,127 @@ describe("Jump rate model tests", () => { const reserves = convertToUnit(2, 19); const badDebt = convertToUnit(1, 19); const expScale = convertToUnit(1, 18); - const blocksPerYear = 10512000; const baseRatePerYear = convertToUnit(2, 12); const multiplierPerYear = convertToUnit(4, 14); const jumpMultiplierPerYear = convertToUnit(2, 18); - const fixture = async () => { - accessControlManager = await smock.fake("AccessControlManager"); - accessControlManager.isAllowedToCall.returns(true); - - const JumpRateModelFactory = await ethers.getContractFactory("JumpRateModelV2"); - jumpRateModel = await JumpRateModelFactory.deploy( - baseRatePerYear, - multiplierPerYear, - jumpMultiplierPerYear, - kink, - accessControlManager.address, - ); - await jumpRateModel.deployed(); - }; - - before(async () => { - await loadFixture(fixture); + const description = getDescription(isTimeBased); + const slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; + + describe(`${description}Jump rate model tests`, async () => { + const fixture = async () => { + accessControlManager = await smock.fake("AccessControlManager"); + accessControlManager.isAllowedToCall.returns(true); + const JumpRateModelFactory = await ethers.getContractFactory("JumpRateModelV2"); + + jumpRateModel = await JumpRateModelFactory.deploy( + baseRatePerYear, + multiplierPerYear, + jumpMultiplierPerYear, + kink, + accessControlManager.address, + isTimeBased, + slotsPerYear, + ); + await jumpRateModel.deployed(); + }; + + before(async () => { + await loadFixture(fixture); + }); + + it("Update jump rate model", async () => { + let baseRatePerBlockOrTimestamp = new BigNumber(baseRatePerYear).dividedBy(slotsPerYear).toFixed(0); + let multiplierPerBlockOrTimestamp = new BigNumber(multiplierPerYear) + .dividedBy(new BigNumber(slotsPerYear)) + .toFixed(0); + let jumpMultiplierPerBlockOrTimestamp = new BigNumber(jumpMultiplierPerYear).dividedBy(slotsPerYear).toFixed(0); + + expect(await jumpRateModel.baseRatePerBlock()).equal(baseRatePerBlockOrTimestamp); + expect(await jumpRateModel.multiplierPerBlock()).equal(multiplierPerBlockOrTimestamp); + expect(await jumpRateModel.jumpMultiplierPerBlock()).equal(jumpMultiplierPerBlockOrTimestamp); + expect(await jumpRateModel.kink()).equal(kink); + + await jumpRateModel.updateJumpRateModel(convertToUnit(3, 12), convertToUnit(5, 14), convertToUnit(2.2, 18), kink); + + baseRatePerBlockOrTimestamp = new BigNumber(convertToUnit(3, 12)).dividedBy(slotsPerYear).toFixed(0); + multiplierPerBlockOrTimestamp = new BigNumber(convertToUnit(5, 14)) + .dividedBy(new BigNumber(slotsPerYear)) + .toFixed(0); + jumpMultiplierPerBlockOrTimestamp = new BigNumber(convertToUnit(2.2, 18)).dividedBy(slotsPerYear).toFixed(0); + + expect(await jumpRateModel.baseRatePerBlock()).equal(baseRatePerBlockOrTimestamp); + expect(await jumpRateModel.multiplierPerBlock()).equal(multiplierPerBlockOrTimestamp); + expect(await jumpRateModel.jumpMultiplierPerBlock()).equal(jumpMultiplierPerBlockOrTimestamp); + expect(await jumpRateModel.kink()).equal(kink); + }); + + it("Utilization rate: borrows and badDebt is zero", async () => { + expect(await jumpRateModel.utilizationRate(cash, 0, reserves, 0)).equal(0); + }); + + it("Should return correct number of blocks", async () => { + expect(await jumpRateModel.blocksOrSecondsPerYear()).to.equal(slotsPerYear); + }); + + it("Utilization rate", async () => { + const utilizationRate = new BigNumber(Number(borrows) + Number(badDebt)) + .multipliedBy(expScale) + .dividedBy(Number(cash) + Number(borrows) + Number(badDebt) - Number(reserves)) + .toFixed(0); + + expect(await jumpRateModel.utilizationRate(cash, borrows, reserves, badDebt)).equal(utilizationRate); + }); + + it("Borrow Rate: below kink utilization", async () => { + const multiplierPerBlockOrTimestamp = (await jumpRateModel.multiplierPerBlock()).toString(); + const baseRatePerBlockOrTimestamp = (await jumpRateModel.baseRatePerBlock()).toString(); + const utilizationRate = (await jumpRateModel.utilizationRate(cash, borrows, reserves, badDebt)).toString(); + + const value = new BigNumber(utilizationRate) + .multipliedBy(multiplierPerBlockOrTimestamp) + .dividedBy(expScale) + .toFixed(0); + + expect(await jumpRateModel.getBorrowRate(cash, borrows, reserves, badDebt)).equal( + Number(value) + Number(baseRatePerBlockOrTimestamp), + ); + }); + + it("Borrow Rate: above kink utilization", async () => { + const multiplierPerBlockOrTimestamp = (await jumpRateModel.multiplierPerBlock()).toString(); + const jumpMultiplierPerBlockOrTimestamp = (await jumpRateModel.jumpMultiplierPerBlock()).toString(); + const baseRatePerBlockOrTimestamp = (await jumpRateModel.baseRatePerBlock()).toString(); + const utilizationRate = ( + await jumpRateModel.utilizationRate(convertToUnit(6, 19), convertToUnit(16, 19), reserves, badDebt) + ).toString(); + + const value = new BigNumber(kink).multipliedBy(multiplierPerBlockOrTimestamp).dividedBy(expScale).toFixed(0); + + const normalRate = Number(value) + Number(baseRatePerBlockOrTimestamp); + const excessUtil = Number(utilizationRate) - Number(kink); + + const jumpValue = new BigNumber(excessUtil) + .multipliedBy(jumpMultiplierPerBlockOrTimestamp) + .dividedBy(expScale) + .toFixed(0); + + expect(await jumpRateModel.getBorrowRate(convertToUnit(6, 19), convertToUnit(16, 19), reserves, badDebt)).equal( + Number(jumpValue) + Number(normalRate), + ); + }); + + it("Supply Rate", async () => { + const reserveMantissa = convertToUnit(1, 17); + const oneMinusReserveFactor = Number(expScale) - Number(reserveMantissa); + const borrowRate = (await jumpRateModel.getBorrowRate(cash, borrows, reserves, badDebt)).toString(); + const rateToPool = new BigNumber(borrowRate).multipliedBy(oneMinusReserveFactor).dividedBy(expScale).toFixed(0); + const rate = new BigNumber(borrows) + .multipliedBy(expScale) + .dividedBy(Number(cash) + Number(borrows) + Number(badDebt) - Number(reserves)); + const supplyRate = new BigNumber(rateToPool).multipliedBy(rate).dividedBy(expScale).toFixed(0); + + expect(await jumpRateModel.getSupplyRate(cash, borrows, reserves, reserveMantissa, badDebt)).equal(supplyRate); + }); }); - - it("Update jump rate model", async () => { - let baseRatePerBlock = new BigNumber(baseRatePerYear).dividedBy(blocksPerYear).toFixed(0); - let multiplierPerBlock = new BigNumber(multiplierPerYear).dividedBy(new BigNumber(blocksPerYear)).toFixed(0); - let jumpMultiplierPerBlock = new BigNumber(jumpMultiplierPerYear).dividedBy(blocksPerYear).toFixed(0); - - expect(await jumpRateModel.baseRatePerBlock()).equal(baseRatePerBlock); - expect(await jumpRateModel.multiplierPerBlock()).equal(multiplierPerBlock); - expect(await jumpRateModel.jumpMultiplierPerBlock()).equal(jumpMultiplierPerBlock); - expect(await jumpRateModel.kink()).equal(kink); - - await jumpRateModel.updateJumpRateModel(convertToUnit(3, 12), convertToUnit(5, 14), convertToUnit(2.2, 18), kink); - - baseRatePerBlock = new BigNumber(convertToUnit(3, 12)).dividedBy(blocksPerYear).toFixed(0); - multiplierPerBlock = new BigNumber(convertToUnit(5, 14)).dividedBy(new BigNumber(blocksPerYear)).toFixed(0); - jumpMultiplierPerBlock = new BigNumber(convertToUnit(2.2, 18)).dividedBy(blocksPerYear).toFixed(0); - - expect(await jumpRateModel.baseRatePerBlock()).equal(baseRatePerBlock); - expect(await jumpRateModel.multiplierPerBlock()).equal(multiplierPerBlock); - expect(await jumpRateModel.jumpMultiplierPerBlock()).equal(jumpMultiplierPerBlock); - expect(await jumpRateModel.kink()).equal(kink); - }); - - it("Utilization rate: borrows and badDebt is zero", async () => { - expect(await jumpRateModel.utilizationRate(cash, 0, reserves, 0)).equal(0); - }); - - it("Utilization rate", async () => { - const utilizationRate = new BigNumber(Number(borrows) + Number(badDebt)) - .multipliedBy(expScale) - .dividedBy(Number(cash) + Number(borrows) + Number(badDebt) - Number(reserves)) - .toFixed(0); - - expect(await jumpRateModel.utilizationRate(cash, borrows, reserves, badDebt)).equal(utilizationRate); - }); - - it("Borrow Rate: below kink utilization", async () => { - const multiplierPerBlock = (await jumpRateModel.multiplierPerBlock()).toString(); - const baseRatePerBlock = (await jumpRateModel.baseRatePerBlock()).toString(); - const utilizationRate = (await jumpRateModel.utilizationRate(cash, borrows, reserves, badDebt)).toString(); - - const value = new BigNumber(utilizationRate).multipliedBy(multiplierPerBlock).dividedBy(expScale).toFixed(0); - - expect(await jumpRateModel.getBorrowRate(cash, borrows, reserves, badDebt)).equal( - Number(value) + Number(baseRatePerBlock), - ); - }); - - it("Borrow Rate: above kink utilization", async () => { - const multiplierPerBlock = (await jumpRateModel.multiplierPerBlock()).toString(); - const jumpMultiplierPerBlock = (await jumpRateModel.jumpMultiplierPerBlock()).toString(); - const baseRatePerBlock = (await jumpRateModel.baseRatePerBlock()).toString(); - const utilizationRate = ( - await jumpRateModel.utilizationRate(convertToUnit(6, 19), convertToUnit(16, 19), reserves, badDebt) - ).toString(); - - const value = new BigNumber(kink).multipliedBy(multiplierPerBlock).dividedBy(expScale).toFixed(0); - - const normalRate = Number(value) + Number(baseRatePerBlock); - const excessUtil = Number(utilizationRate) - Number(kink); - - const jumpValue = new BigNumber(excessUtil).multipliedBy(jumpMultiplierPerBlock).dividedBy(expScale).toFixed(0); - - expect(await jumpRateModel.getBorrowRate(convertToUnit(6, 19), convertToUnit(16, 19), reserves, badDebt)).equal( - Number(jumpValue) + Number(normalRate), - ); - }); - - it("Supply Rate", async () => { - const reserveMantissa = convertToUnit(1, 17); - const oneMinusReserveFactor = Number(expScale) - Number(reserveMantissa); - const borrowRate = (await jumpRateModel.getBorrowRate(cash, borrows, reserves, badDebt)).toString(); - const rateToPool = new BigNumber(borrowRate).multipliedBy(oneMinusReserveFactor).dividedBy(expScale).toFixed(0); - const rate = new BigNumber(borrows) - .multipliedBy(expScale) - .dividedBy(Number(cash) + Number(borrows) + Number(badDebt) - Number(reserves)); - const supplyRate = new BigNumber(rateToPool).multipliedBy(rate).dividedBy(expScale).toFixed(0); - - expect(await jumpRateModel.getSupplyRate(cash, borrows, reserves, reserveMantissa, badDebt)).equal(supplyRate); - }); -}); +} diff --git a/tests/hardhat/Lens/PoolLens.ts b/tests/hardhat/Lens/PoolLens.ts index 0c78ddf95..82711bc85 100644 --- a/tests/hardhat/Lens/PoolLens.ts +++ b/tests/hardhat/Lens/PoolLens.ts @@ -5,6 +5,7 @@ import { BigNumberish, Signer } from "ethers"; import { parseUnits } from "ethers/lib/utils"; import { ethers, upgrades } from "hardhat"; +import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../../helpers/deploymentConfig"; import { AccessControlManager, Beacon, @@ -20,6 +21,7 @@ import { WhitePaperInterestRateModel__factory, } from "../../../typechain"; import { makeVToken } from "../util/TokenTestHelpers"; +import { getDescription } from "../util/descriptionHelpers"; // Disable a warning about mixing beacons and transparent proxies upgrades.silenceWarnings(); @@ -44,397 +46,407 @@ const assertVTokenMetadata = (vTokenMetadataActual: any, vTokenMetadataExpected: }); }; -describe("PoolLens", async function () { - let poolRegistry: PoolRegistry; - let poolRegistryAddress: string; - let vTokenBeacon: Beacon; - let mockDAI: MockToken; - let mockWBTC: MockToken; - let vDAI: VToken; - let vWBTC: VToken; - let priceOracle: MockPriceOracle; - let comptroller1Proxy: Comptroller; - let comptroller2Proxy: Comptroller; - let poolLens: PoolLens; - let ownerAddress: string; - let fakeAccessControlManager: FakeContract; - let closeFactor1: BigNumberish; - let closeFactor2: BigNumberish; - let liquidationIncentive1: BigNumberish; - let liquidationIncentive2: BigNumberish; - const minLiquidatableCollateral = parseUnits("100", 18); - const maxLoopsLimit = 150; - const defaultBtcPrice = "21000.34"; - const defaultDaiPrice = "1"; - let borrowerWbtc: Signer; - let borrowerDai: Signer; - - interface PoolRegistryFixture { - poolRegistry: PoolRegistry; - fakeAccessControlManager: FakeContract; - } - - const poolRegistryFixture = async (): Promise => { - fakeAccessControlManager = await smock.fake("AccessControlManager"); - fakeAccessControlManager.isAllowedToCall.returns(true); - - const PoolRegistry = await ethers.getContractFactory("PoolRegistry"); - poolRegistry = (await upgrades.deployProxy(PoolRegistry, [fakeAccessControlManager.address])) as PoolRegistry; - - return { poolRegistry, fakeAccessControlManager }; - }; - - /** - * Deploying required contracts along with the poolRegistry. - */ - before(async function () { - const [owner, ...rest] = await ethers.getSigners(); - [borrowerWbtc, borrowerDai] = rest; - ownerAddress = await owner.getAddress(); - - ({ poolRegistry, fakeAccessControlManager } = await loadFixture(poolRegistryFixture)); - poolRegistryAddress = poolRegistry.address; - - const MockPriceOracle = await ethers.getContractFactory("MockPriceOracle"); - priceOracle = await MockPriceOracle.deploy(); - - closeFactor1 = parseUnits("0.05", 18); - liquidationIncentive1 = parseUnits("1", 18); - - const Comptroller = await ethers.getContractFactory("Comptroller"); - const comptrollerBeacon = await upgrades.deployBeacon(Comptroller, { constructorArgs: [poolRegistry.address] }); - - [comptroller1Proxy, comptroller2Proxy] = await Promise.all( - [...Array(3)].map(async () => { - const comptroller = await upgrades.deployBeaconProxy(comptrollerBeacon, Comptroller, [ - maxLoopsLimit, - fakeAccessControlManager.address, - ]); - await comptroller.setPriceOracle(priceOracle.address); - return comptroller as Comptroller; - }), - ); - - // Registering the first pool - await poolRegistry.addPool( - "Pool 1", - comptroller1Proxy.address, - closeFactor1, - liquidationIncentive1, - minLiquidatableCollateral, - ); - - closeFactor2 = parseUnits("0.05", 18); - liquidationIncentive2 = parseUnits("1", 18); - - // Registering the second pool - await poolRegistry.addPool( - "Pool 2", - comptroller2Proxy.address, - closeFactor2, - liquidationIncentive2, - minLiquidatableCollateral, - ); - - const MockToken = await ethers.getContractFactory("MockToken"); - mockDAI = await MockToken.deploy("MakerDAO", "DAI", 18); - await mockDAI.faucet(parseUnits("1000", 18)); - - mockWBTC = await MockToken.deploy("Bitcoin", "BTC", 8); - await mockWBTC.faucet(parseUnits("1000", 8)); - - await priceOracle.setPrice(mockDAI.address, parseUnits(defaultDaiPrice, 18)); - await priceOracle.setPrice(mockWBTC.address, parseUnits(defaultBtcPrice, 28)); - - // Get all pools list. - const pools = await poolRegistry.callStatic.getAllPools(); - expect(pools[0].name).equal("Pool 1"); - expect(pools[1].name).equal("Pool 2"); - - const initialSupply = parseUnits("1000", 18); - const RateModel = await ethers.getContractFactory( - "WhitePaperInterestRateModel", - ); - const whitePaperInterestRateModel = await RateModel.deploy(0, parseUnits("0.04", 18)); - vWBTC = await makeVToken({ - underlying: mockWBTC, - comptroller: comptroller1Proxy, - accessControlManager: fakeAccessControlManager, - decimals: 8, - initialExchangeRateMantissa: parseUnits("1", 18), - admin: owner, - interestRateModel: whitePaperInterestRateModel, - beacon: vTokenBeacon, - }); - - await mockWBTC.faucet(initialSupply); - await mockWBTC.approve(poolRegistry.address, initialSupply); - await poolRegistry.addMarket({ - vToken: vWBTC.address, - collateralFactor: parseUnits("0.7", 18), - liquidationThreshold: parseUnits("0.7", 18), - initialSupply, - vTokenReceiver: owner.address, - supplyCap: parseUnits("4000", 18), - borrowCap: parseUnits("2000", 18), - }); - - vDAI = await makeVToken({ - underlying: mockDAI, - comptroller: comptroller1Proxy, - accessControlManager: fakeAccessControlManager, - decimals: 18, - initialExchangeRateMantissa: parseUnits("1", 18), - admin: owner, - interestRateModel: whitePaperInterestRateModel, - beacon: vTokenBeacon, - }); - - await mockDAI.faucet(initialSupply); - await mockDAI.approve(poolRegistry.address, initialSupply); - await poolRegistry.addMarket({ - vToken: vDAI.address, - collateralFactor: parseUnits("0.7", 18), - liquidationThreshold: parseUnits("0.7", 18), - initialSupply, - vTokenReceiver: owner.address, - supplyCap: initialSupply, - borrowCap: initialSupply, - }); - - await poolRegistry.updatePoolMetadata(comptroller1Proxy.address, { - category: "High market cap", - logoURL: "http://venis.io/pool1", - description: "Pool1 description", - }); - - await poolRegistry.updatePoolMetadata(comptroller2Proxy.address, { - category: "Low market cap", - logoURL: "http://highrisk.io/pool2", - description: "Pool2 description", - }); - - const vWBTCAddress = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); - const vDAIAddress = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); +for (const isTimeBased of [false, true]) { + const description = getDescription(isTimeBased); + const slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; + + describe(`${description}PoolLens`, async () => { + let poolRegistry: PoolRegistry; + let poolRegistryAddress: string; + let vTokenBeacon: Beacon; + let mockDAI: MockToken; + let mockWBTC: MockToken; + let vDAI: VToken; + let vWBTC: VToken; + let priceOracle: MockPriceOracle; + let comptroller1Proxy: Comptroller; + let comptroller2Proxy: Comptroller; + let poolLens: PoolLens; + let ownerAddress: string; + let fakeAccessControlManager: FakeContract; + let closeFactor1: BigNumberish; + let closeFactor2: BigNumberish; + let liquidationIncentive1: BigNumberish; + let liquidationIncentive2: BigNumberish; + const minLiquidatableCollateral = parseUnits("100", 18); + const maxLoopsLimit = 150; + const defaultBtcPrice = "21000.34"; + const defaultDaiPrice = "1"; + let borrowerWbtc: Signer; + let borrowerDai: Signer; + + interface PoolRegistryFixture { + poolRegistry: PoolRegistry; + fakeAccessControlManager: FakeContract; + } - vWBTC = await ethers.getContractAt("VToken", vWBTCAddress); - vDAI = await ethers.getContractAt("VToken", vDAIAddress); + const poolRegistryFixture = async (): Promise => { + fakeAccessControlManager = await smock.fake("AccessControlManager"); + fakeAccessControlManager.isAllowedToCall.returns(true); + + const PoolRegistry = await ethers.getContractFactory("PoolRegistry"); + poolRegistry = (await upgrades.deployProxy(PoolRegistry, [fakeAccessControlManager.address])) as PoolRegistry; + + return { poolRegistry, fakeAccessControlManager }; + }; + + /** + * Deploying required contracts along with the poolRegistry. + */ + before(async () => { + const [owner, ...rest] = await ethers.getSigners(); + [borrowerWbtc, borrowerDai] = rest; + ownerAddress = await owner.getAddress(); + + ({ poolRegistry, fakeAccessControlManager } = await loadFixture(poolRegistryFixture)); + poolRegistryAddress = poolRegistry.address; + + const MockPriceOracle = await ethers.getContractFactory("MockPriceOracle"); + priceOracle = await MockPriceOracle.deploy(); + + closeFactor1 = parseUnits("0.05", 18); + liquidationIncentive1 = parseUnits("1", 18); + + const Comptroller = await ethers.getContractFactory("Comptroller"); + const comptrollerBeacon = await upgrades.deployBeacon(Comptroller, { constructorArgs: [poolRegistry.address] }); + + [comptroller1Proxy, comptroller2Proxy] = await Promise.all( + [...Array(3)].map(async () => { + const comptroller = await upgrades.deployBeaconProxy(comptrollerBeacon, Comptroller, [ + maxLoopsLimit, + fakeAccessControlManager.address, + ]); + await comptroller.setPriceOracle(priceOracle.address); + return comptroller as Comptroller; + }), + ); - // Enter Markets - await comptroller1Proxy.enterMarkets([vDAI.address, vWBTC.address]); - await comptroller1Proxy.connect(owner).enterMarkets([vDAI.address, vWBTC.address]); + // Registering the first pool + await poolRegistry.addPool( + "Pool 1", + comptroller1Proxy.address, + closeFactor1, + liquidationIncentive1, + minLiquidatableCollateral, + ); - const PoolLens = await ethers.getContractFactory("PoolLens"); - poolLens = await PoolLens.deploy(); - }); + closeFactor2 = parseUnits("0.05", 18); + liquidationIncentive2 = parseUnits("1", 18); - describe("PoolView Tests", () => { - it("get All Pools", async function () { - const poolData = await poolLens.getAllPools(poolRegistryAddress); - - expect(poolData.length).equal(2); - - const venusPool1Actual = poolData[0]; - - expect(venusPool1Actual.name).equal("Pool 1"); - expect(venusPool1Actual.creator).equal(ownerAddress); - expect(venusPool1Actual.comptroller).equal(comptroller1Proxy.address); - expect(venusPool1Actual.category).equal("High market cap"); - expect(venusPool1Actual.logoURL).equal("http://venis.io/pool1"); - expect(venusPool1Actual.description).equal("Pool1 description"); - expect(venusPool1Actual.priceOracle).equal(priceOracle.address); - expect(venusPool1Actual.closeFactor).equal(closeFactor1); - expect(venusPool1Actual.liquidationIncentive).equal(liquidationIncentive1); - expect(venusPool1Actual.minLiquidatableCollateral).equal(minLiquidatableCollateral); - - const vTokensActual = venusPool1Actual.vTokens; - expect(vTokensActual.length).equal(2); - - // get VToken for Asset-1 : WBTC - const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); - const vTokenMetadataWBTCExpected = await poolLens.vTokenMetadata(vTokenAddressWBTC); - const vTokenMetadataWBTCActual = vTokensActual[0]; - assertVTokenMetadata(vTokenMetadataWBTCActual, vTokenMetadataWBTCExpected); - - // get VToken for Asset-2 : DAI - const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); - const vTokenMetadataDAIExpected = await poolLens.vTokenMetadata(vTokenAddressDAI); - const vTokenMetadataDAIActual = vTokensActual[1]; - assertVTokenMetadata(vTokenMetadataDAIActual, vTokenMetadataDAIExpected); - - const venusPool2Actual = poolData[1]; - - expect(venusPool2Actual.name).equal("Pool 2"); - expect(venusPool2Actual.creator).equal(ownerAddress); - expect(venusPool2Actual.comptroller).equal(comptroller2Proxy.address); - expect(venusPool2Actual.category).equal("Low market cap"); - expect(venusPool2Actual.logoURL).equal("http://highrisk.io/pool2"); - expect(venusPool2Actual.description).equal("Pool2 description"); - expect(venusPool1Actual.priceOracle).equal(priceOracle.address); - expect(venusPool1Actual.closeFactor).equal(closeFactor2); - expect(venusPool1Actual.liquidationIncentive).equal(liquidationIncentive2); - expect(venusPool1Actual.minLiquidatableCollateral).equal(minLiquidatableCollateral); - }); + // Registering the second pool + await poolRegistry.addPool( + "Pool 2", + comptroller2Proxy.address, + closeFactor2, + liquidationIncentive2, + minLiquidatableCollateral, + ); - it("getPoolData By Comptroller", async function () { - const poolData = await poolLens.getPoolByComptroller(poolRegistryAddress, comptroller1Proxy.address); - - expect(poolData.name).equal("Pool 1"); - expect(poolData.creator).equal(ownerAddress); - expect(poolData.comptroller).equal(comptroller1Proxy.address); - expect(poolData.category).equal("High market cap"); - expect(poolData.logoURL).equal("http://venis.io/pool1"); - expect(poolData.description).equal("Pool1 description"); - expect(poolData.priceOracle).equal(priceOracle.address); - expect(poolData.closeFactor).equal(closeFactor1); - expect(poolData.liquidationIncentive).equal(liquidationIncentive1); - expect(poolData.minLiquidatableCollateral).equal(minLiquidatableCollateral); - - const vTokensActual = poolData.vTokens; - expect(vTokensActual.length).equal(2); - - // get VToken for Asset-1 : WBTC - const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); - const vTokenMetadataWBTCExpected = await poolLens.vTokenMetadata(vTokenAddressWBTC); - const vTokenMetadataWBTCActual = vTokensActual[0]; - assertVTokenMetadata(vTokenMetadataWBTCActual, vTokenMetadataWBTCExpected); - - // get VToken for Asset-2 : DAI - const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); - const vTokenMetadataDAIExpected = await poolLens.vTokenMetadata(vTokenAddressDAI); - const vTokenMetadataDAIActual = vTokensActual[1]; - assertVTokenMetadata(vTokenMetadataDAIActual, vTokenMetadataDAIExpected); - }); - }); + const MockToken = await ethers.getContractFactory("MockToken"); + mockDAI = await MockToken.deploy("MakerDAO", "DAI", 18); + await mockDAI.faucet(parseUnits("1000", 18)); - describe("PoolLens - VTokens Query Tests", async function () { - it("get all info of pools user specific", async function () { - const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); - const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); - const res = await poolLens.callStatic.vTokenBalancesAll([vTokenAddressWBTC, vTokenAddressDAI], ownerAddress); - expect(res[0][0]).equal(vTokenAddressWBTC); - expect(res[1][0]).equal(vTokenAddressDAI); - }); + mockWBTC = await MockToken.deploy("Bitcoin", "BTC", 8); + await mockWBTC.faucet(parseUnits("1000", 8)); - it("get underlying price", async function () { - const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); - const res = await poolLens.vTokenUnderlyingPrice(vTokenAddressDAI); - expect(res[1]).equal(parseUnits("1", 18)); - }); + await priceOracle.setPrice(mockDAI.address, parseUnits(defaultDaiPrice, 18)); + await priceOracle.setPrice(mockWBTC.address, parseUnits(defaultBtcPrice, 28)); - it("get underlying price all", async function () { - const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); - const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); - const res = await poolLens.vTokenUnderlyingPriceAll([vTokenAddressDAI, vTokenAddressWBTC]); - expect(res[0][1]).equal(parseUnits("1", 18)); - expect(res[1][1]).equal(parseUnits("21000.34", 28)); - }); + // Get all pools list. + const pools = await poolRegistry.callStatic.getAllPools(); + expect(pools[0].name).equal("Pool 1"); + expect(pools[1].name).equal("Pool 2"); - it("get underlying price all", async function () { - const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); - const vTokenAddressWBTCPool = await poolLens.getVTokenForAsset( - poolRegistry.address, - comptroller1Proxy.address, - mockWBTC.address, + const initialSupply = parseUnits("1000", 18); + const RateModel = await ethers.getContractFactory( + "WhitePaperInterestRateModel", ); - expect(vTokenAddressWBTC).equal(vTokenAddressWBTCPool); - }); - it("is correct for WBTC as underlyingAsset", async () => { - // get CToken for Asset-1 : WBTC - const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); - const vTokenMetadataActual = await poolLens.vTokenMetadata(vTokenAddressWBTC); - - const vTokenMetadataActualParsed = cullTuple(vTokenMetadataActual); - expect(vTokenMetadataActualParsed["vToken"]).equal(vTokenAddressWBTC); - expect(vTokenMetadataActualParsed["exchangeRateCurrent"]).equal(parseUnits("1", 18)); - expect(vTokenMetadataActualParsed["supplyRatePerBlock"]).equal("0"); - expect(vTokenMetadataActualParsed["borrowRatePerBlock"]).equal("0"); - expect(vTokenMetadataActualParsed["reserveFactorMantissa"]).equal(parseUnits("0.3", 18)); - expect(vTokenMetadataActualParsed["supplyCaps"]).equal("4000000000000000000000"); - expect(vTokenMetadataActualParsed["borrowCaps"]).equal("2000000000000000000000"); - expect(vTokenMetadataActualParsed["totalBorrows"]).equal("0"); - expect(vTokenMetadataActualParsed["totalReserves"]).equal("0"); - expect(vTokenMetadataActualParsed["totalSupply"]).equal(parseUnits("10000000000000", 8)); - expect(vTokenMetadataActualParsed["totalCash"]).equal(parseUnits("10000000000000", 8)); - expect(vTokenMetadataActualParsed["isListed"]).equal("true"); - expect(vTokenMetadataActualParsed["collateralFactorMantissa"]).equal("700000000000000000"); - expect(vTokenMetadataActualParsed["underlyingAssetAddress"]).equal(mockWBTC.address); - expect(vTokenMetadataActualParsed["vTokenDecimals"]).equal("8"); - expect(vTokenMetadataActualParsed["underlyingDecimals"]).equal("8"); + const whitePaperInterestRateModel = await RateModel.deploy(0, parseUnits("0.04", 18), isTimeBased, slotsPerYear); + vWBTC = await makeVToken({ + underlying: mockWBTC, + comptroller: comptroller1Proxy, + accessControlManager: fakeAccessControlManager, + decimals: 8, + initialExchangeRateMantissa: parseUnits("1", 18), + admin: owner, + interestRateModel: whitePaperInterestRateModel, + beacon: vTokenBeacon, + isTimeBased: isTimeBased, + blocksPerYear: slotsPerYear, + }); + + vDAI = await makeVToken({ + underlying: mockDAI, + comptroller: comptroller1Proxy, + accessControlManager: fakeAccessControlManager, + decimals: 18, + initialExchangeRateMantissa: parseUnits("1", 18), + admin: owner, + interestRateModel: whitePaperInterestRateModel, + beacon: vTokenBeacon, + isTimeBased: isTimeBased, + blocksPerYear: slotsPerYear, + }); + + await mockWBTC.faucet(initialSupply); + await mockWBTC.approve(poolRegistry.address, initialSupply); + await poolRegistry.addMarket({ + vToken: vWBTC.address, + collateralFactor: parseUnits("0.7", 18), + liquidationThreshold: parseUnits("0.7", 18), + initialSupply, + vTokenReceiver: owner.address, + supplyCap: parseUnits("4000", 18), + borrowCap: parseUnits("2000", 18), + }); + + await mockDAI.faucet(initialSupply); + await mockDAI.approve(poolRegistry.address, initialSupply); + await poolRegistry.addMarket({ + vToken: vDAI.address, + collateralFactor: parseUnits("0.7", 18), + liquidationThreshold: parseUnits("0.7", 18), + initialSupply, + vTokenReceiver: owner.address, + supplyCap: initialSupply, + borrowCap: initialSupply, + }); + + await poolRegistry.updatePoolMetadata(comptroller1Proxy.address, { + category: "High market cap", + logoURL: "http://venis.io/pool1", + description: "Pool1 description", + }); + + await poolRegistry.updatePoolMetadata(comptroller2Proxy.address, { + category: "Low market cap", + logoURL: "http://highrisk.io/pool2", + description: "Pool2 description", + }); + + const vWBTCAddress = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); + const vDAIAddress = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); + + vWBTC = await ethers.getContractAt("VToken", vWBTCAddress); + vDAI = await ethers.getContractAt("VToken", vDAIAddress); + + // Enter Markets + await comptroller1Proxy.enterMarkets([vDAI.address, vWBTC.address]); + await comptroller1Proxy.connect(owner).enterMarkets([vDAI.address, vWBTC.address]); + + const PoolLens = await ethers.getContractFactory("PoolLens"); + poolLens = await PoolLens.deploy(isTimeBased, slotsPerYear); }); - it("is correct minted for user", async () => { - const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); - const vTokenBalance = await poolLens.callStatic.vTokenBalances(vTokenAddressWBTC, ownerAddress); - expect(vTokenBalance["balanceOfUnderlying"]).equal(parseUnits("10000000000000", 8)); - expect(vTokenBalance["balanceOf"]).equal(parseUnits("10000000000000", 8)); + describe(`${description}PoolView Tests`, () => { + it("get All Pools", async function () { + const poolData = await poolLens.getAllPools(poolRegistryAddress); + + expect(poolData.length).equal(2); + + const venusPool1Actual = poolData[0]; + + expect(venusPool1Actual.name).equal("Pool 1"); + expect(venusPool1Actual.creator).equal(ownerAddress); + expect(venusPool1Actual.comptroller).equal(comptroller1Proxy.address); + expect(venusPool1Actual.category).equal("High market cap"); + expect(venusPool1Actual.logoURL).equal("http://venis.io/pool1"); + expect(venusPool1Actual.description).equal("Pool1 description"); + expect(venusPool1Actual.priceOracle).equal(priceOracle.address); + expect(venusPool1Actual.closeFactor).equal(closeFactor1); + expect(venusPool1Actual.liquidationIncentive).equal(liquidationIncentive1); + expect(venusPool1Actual.minLiquidatableCollateral).equal(minLiquidatableCollateral); + + const vTokensActual = venusPool1Actual.vTokens; + expect(vTokensActual.length).equal(2); + + // get VToken for Asset-1 : WBTC + const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); + const vTokenMetadataWBTCExpected = await poolLens.vTokenMetadata(vTokenAddressWBTC); + const vTokenMetadataWBTCActual = vTokensActual[0]; + assertVTokenMetadata(vTokenMetadataWBTCActual, vTokenMetadataWBTCExpected); + + // get VToken for Asset-2 : DAI + const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); + const vTokenMetadataDAIExpected = await poolLens.vTokenMetadata(vTokenAddressDAI); + const vTokenMetadataDAIActual = vTokensActual[1]; + assertVTokenMetadata(vTokenMetadataDAIActual, vTokenMetadataDAIExpected); + + const venusPool2Actual = poolData[1]; + + expect(venusPool2Actual.name).equal("Pool 2"); + expect(venusPool2Actual.creator).equal(ownerAddress); + expect(venusPool2Actual.comptroller).equal(comptroller2Proxy.address); + expect(venusPool2Actual.category).equal("Low market cap"); + expect(venusPool2Actual.logoURL).equal("http://highrisk.io/pool2"); + expect(venusPool2Actual.description).equal("Pool2 description"); + expect(venusPool1Actual.priceOracle).equal(priceOracle.address); + expect(venusPool1Actual.closeFactor).equal(closeFactor2); + expect(venusPool1Actual.liquidationIncentive).equal(liquidationIncentive2); + expect(venusPool1Actual.minLiquidatableCollateral).equal(minLiquidatableCollateral); + }); + + it("getPoolData By Comptroller", async function () { + const poolData = await poolLens.getPoolByComptroller(poolRegistryAddress, comptroller1Proxy.address); + + expect(poolData.name).equal("Pool 1"); + expect(poolData.creator).equal(ownerAddress); + expect(poolData.comptroller).equal(comptroller1Proxy.address); + expect(poolData.category).equal("High market cap"); + expect(poolData.logoURL).equal("http://venis.io/pool1"); + expect(poolData.description).equal("Pool1 description"); + expect(poolData.priceOracle).equal(priceOracle.address); + expect(poolData.closeFactor).equal(closeFactor1); + expect(poolData.liquidationIncentive).equal(liquidationIncentive1); + expect(poolData.minLiquidatableCollateral).equal(minLiquidatableCollateral); + + const vTokensActual = poolData.vTokens; + expect(vTokensActual.length).equal(2); + + // get VToken for Asset-1 : WBTC + const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); + const vTokenMetadataWBTCExpected = await poolLens.vTokenMetadata(vTokenAddressWBTC); + const vTokenMetadataWBTCActual = vTokensActual[0]; + assertVTokenMetadata(vTokenMetadataWBTCActual, vTokenMetadataWBTCExpected); + + // get VToken for Asset-2 : DAI + const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); + const vTokenMetadataDAIExpected = await poolLens.vTokenMetadata(vTokenAddressDAI); + const vTokenMetadataDAIActual = vTokensActual[1]; + assertVTokenMetadata(vTokenMetadataDAIActual, vTokenMetadataDAIExpected); + }); }); - }); - describe("Shortfall view functions", () => { - it("getPoolBadDebt - no pools have debt", async () => { - const resp = await poolLens.getPoolBadDebt(comptroller1Proxy.address); - - expect(resp.comptroller).to.be.equal(comptroller1Proxy.address); - expect(resp.totalBadDebtUsd).to.be.equal(0); - - expect(resp.badDebts[0][0]).to.be.equal(vWBTC.address); - expect(resp.badDebts[0][1].toString()).to.be.equal("0"); - - expect(resp.badDebts[1][0]).to.be.equal(vDAI.address); - expect(resp.badDebts[1][1].toString()).to.be.equal("0"); + describe(`${description}PoolLens - VTokens Query Tests`, async function () { + it("get all info of pools user specific", async function () { + const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); + const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); + const res = await poolLens.callStatic.vTokenBalancesAll([vTokenAddressWBTC, vTokenAddressDAI], ownerAddress); + expect(res[0][0]).equal(vTokenAddressWBTC); + expect(res[1][0]).equal(vTokenAddressDAI); + }); + + it("get underlying price", async function () { + const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); + const res = await poolLens.vTokenUnderlyingPrice(vTokenAddressDAI); + expect(res[1]).equal(parseUnits("1", 18)); + }); + + it("get underlying price all", async function () { + const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); + const vTokenAddressDAI = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); + const res = await poolLens.vTokenUnderlyingPriceAll([vTokenAddressDAI, vTokenAddressWBTC]); + expect(res[0][1]).equal(parseUnits("1", 18)); + expect(res[1][1]).equal(parseUnits("21000.34", 28)); + }); + + it("get underlying price all", async function () { + const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); + const vTokenAddressWBTCPool = await poolLens.getVTokenForAsset( + poolRegistry.address, + comptroller1Proxy.address, + mockWBTC.address, + ); + expect(vTokenAddressWBTC).equal(vTokenAddressWBTCPool); + }); + + it("is correct for WBTC as underlyingAsset", async () => { + // get CToken for Asset-1 : WBTC + const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); + const vTokenMetadataActual = await poolLens.vTokenMetadata(vTokenAddressWBTC); + + const vTokenMetadataActualParsed = cullTuple(vTokenMetadataActual); + expect(vTokenMetadataActualParsed["vToken"]).equal(vTokenAddressWBTC); + expect(vTokenMetadataActualParsed["exchangeRateCurrent"]).equal(parseUnits("1", 18)); + expect(vTokenMetadataActualParsed["supplyRatePerBlock"]).equal("0"); + expect(vTokenMetadataActualParsed["borrowRatePerBlock"]).equal("0"); + expect(vTokenMetadataActualParsed["reserveFactorMantissa"]).equal(parseUnits("0.3", 18)); + expect(vTokenMetadataActualParsed["supplyCaps"]).equal("4000000000000000000000"); + expect(vTokenMetadataActualParsed["borrowCaps"]).equal("2000000000000000000000"); + expect(vTokenMetadataActualParsed["totalBorrows"]).equal("0"); + expect(vTokenMetadataActualParsed["totalReserves"]).equal("0"); + expect(vTokenMetadataActualParsed["totalSupply"]).equal(parseUnits("10000000000000", 8)); + expect(vTokenMetadataActualParsed["totalCash"]).equal(parseUnits("10000000000000", 8)); + expect(vTokenMetadataActualParsed["isListed"]).equal("true"); + expect(vTokenMetadataActualParsed["collateralFactorMantissa"]).equal("700000000000000000"); + expect(vTokenMetadataActualParsed["underlyingAssetAddress"]).equal(mockWBTC.address); + expect(vTokenMetadataActualParsed["vTokenDecimals"]).equal("8"); + expect(vTokenMetadataActualParsed["underlyingDecimals"]).equal("8"); + }); + + it("is correct minted for user", async () => { + const vTokenAddressWBTC = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); + const vTokenBalance = await poolLens.callStatic.vTokenBalances(vTokenAddressWBTC, ownerAddress); + expect(vTokenBalance["balanceOfUnderlying"]).equal(parseUnits("10000000000000", 8)); + expect(vTokenBalance["balanceOf"]).equal(parseUnits("10000000000000", 8)); + }); }); - it("getPoolBadDebt - all pools have debt", async () => { - const [owner] = await ethers.getSigners(); - // Setup - await comptroller1Proxy.setMarketSupplyCaps( - [vWBTC.address, vDAI.address], - [parseUnits("9000000000", 18), parseUnits("9000000000", 18)], - ); - - await mockWBTC.connect(borrowerDai).faucet(parseUnits("20", 18)); - await mockWBTC.connect(borrowerDai).approve(vWBTC.address, parseUnits("20", 18)); - await vWBTC.connect(borrowerDai).mint(parseUnits("2", 18)); - await comptroller1Proxy.connect(borrowerDai).enterMarkets([vWBTC.address]); - await vDAI.connect(borrowerDai).borrow(parseUnits("0.05", 18)); - await mine(1); - - await mockDAI.connect(borrowerWbtc).faucet(parseUnits("900000000", 18)); - await mockDAI.connect(borrowerWbtc).approve(vDAI.address, parseUnits("9000000000", 18)); - await mockDAI.connect(borrowerWbtc).approve(vDAI.address, parseUnits("9000000000", 18)); - await vDAI.connect(borrowerWbtc).mint(parseUnits("900000000", 18)); - await comptroller1Proxy.connect(borrowerWbtc).enterMarkets([vDAI.address]); - await vWBTC.connect(borrowerWbtc).borrow(parseUnits("0.000001", 18)); - await mine(1); - - await mockDAI.connect(owner).approve(vDAI.address, parseUnits("9000000000", 18)); - await mockWBTC.connect(owner).approve(vWBTC.address, parseUnits("9000000000", 18)); - await priceOracle.setPrice(mockWBTC.address, parseUnits("0.000000000000001", 18)); - await mine(1); - - await comptroller1Proxy.connect(owner).healAccount(await borrowerDai.getAddress()); - - await priceOracle.setPrice(mockWBTC.address, parseUnits(defaultBtcPrice, 28)); - await priceOracle.setPrice(mockDAI.address, parseUnits("0.0000000000000001", 18)); - await comptroller1Proxy.connect(owner).healAccount(await borrowerWbtc.getAddress()); - // End Setup - - const resp = await poolLens.getPoolBadDebt(comptroller1Proxy.address); - - expect(resp.comptroller).to.be.equal(comptroller1Proxy.address); - expect(resp.totalBadDebtUsd).to.be.equal("210003400000000000000000005"); - - expect(resp.badDebts[1][0]).to.be.equal(vDAI.address); - expect(resp.badDebts[1][1].toString()).to.be.equal("5"); - - expect(resp.badDebts[0][0]).to.be.equal(vWBTC.address); - expect(resp.badDebts[0][1].toString()).to.be.equal("210003400000000000000000000"); - - // Cleanup - await priceOracle.setPrice(mockDAI.address, parseUnits(defaultDaiPrice, 18)); - await priceOracle.setPrice(mockWBTC.address, parseUnits(defaultBtcPrice, 28)); + describe("Shortfall view functions", () => { + it("getPoolBadDebt - no pools have debt", async () => { + const resp = await poolLens.getPoolBadDebt(comptroller1Proxy.address); + + expect(resp.comptroller).to.be.equal(comptroller1Proxy.address); + expect(resp.totalBadDebtUsd).to.be.equal(0); + + expect(resp.badDebts[0][0]).to.be.equal(vWBTC.address); + expect(resp.badDebts[0][1].toString()).to.be.equal("0"); + + expect(resp.badDebts[1][0]).to.be.equal(vDAI.address); + expect(resp.badDebts[1][1].toString()).to.be.equal("0"); + }); + + it("getPoolBadDebt - all pools have debt", async () => { + const [owner] = await ethers.getSigners(); + // Setup + await comptroller1Proxy.setMarketSupplyCaps( + [vWBTC.address, vDAI.address], + [parseUnits("9000000000", 18), parseUnits("9000000000", 18)], + ); + + await mockWBTC.connect(borrowerDai).faucet(parseUnits("20", 18)); + await mockWBTC.connect(borrowerDai).approve(vWBTC.address, parseUnits("20", 18)); + await vWBTC.connect(borrowerDai).mint(parseUnits("2", 18)); + await comptroller1Proxy.connect(borrowerDai).enterMarkets([vWBTC.address]); + await vDAI.connect(borrowerDai).borrow(parseUnits("0.05", 18)); + await mine(1); + + await mockDAI.connect(borrowerWbtc).faucet(parseUnits("900000000", 18)); + await mockDAI.connect(borrowerWbtc).approve(vDAI.address, parseUnits("9000000000", 18)); + await mockDAI.connect(borrowerWbtc).approve(vDAI.address, parseUnits("9000000000", 18)); + await vDAI.connect(borrowerWbtc).mint(parseUnits("900000000", 18)); + await comptroller1Proxy.connect(borrowerWbtc).enterMarkets([vDAI.address]); + await vWBTC.connect(borrowerWbtc).borrow(parseUnits("0.000001", 18)); + await mine(1); + + await mockDAI.connect(owner).approve(vDAI.address, parseUnits("9000000000", 18)); + await mockWBTC.connect(owner).approve(vWBTC.address, parseUnits("9000000000", 18)); + await priceOracle.setPrice(mockWBTC.address, parseUnits("0.000000000000001", 18)); + await mine(1); + + await comptroller1Proxy.connect(owner).healAccount(await borrowerDai.getAddress()); + + await priceOracle.setPrice(mockWBTC.address, parseUnits(defaultBtcPrice, 28)); + await priceOracle.setPrice(mockDAI.address, parseUnits("0.0000000000000001", 18)); + await comptroller1Proxy.connect(owner).healAccount(await borrowerWbtc.getAddress()); + // End Setup + + const resp = await poolLens.getPoolBadDebt(comptroller1Proxy.address); + + expect(resp.comptroller).to.be.equal(comptroller1Proxy.address); + expect(resp.totalBadDebtUsd).to.be.equal("210003400000000000000000005"); + + expect(resp.badDebts[1][0]).to.be.equal(vDAI.address); + expect(resp.badDebts[1][1].toString()).to.be.equal("5"); + + expect(resp.badDebts[0][0]).to.be.equal(vWBTC.address); + expect(resp.badDebts[0][1].toString()).to.be.equal("210003400000000000000000000"); + + // Cleanup + await priceOracle.setPrice(mockDAI.address, parseUnits(defaultDaiPrice, 18)); + await priceOracle.setPrice(mockWBTC.address, parseUnits(defaultBtcPrice, 28)); + }); }); }); -}); +} diff --git a/tests/hardhat/Lens/RewardsSummary.ts b/tests/hardhat/Lens/RewardsSummary.ts index 6a72d37f0..7cf08c11c 100644 --- a/tests/hardhat/Lens/RewardsSummary.ts +++ b/tests/hardhat/Lens/RewardsSummary.ts @@ -4,8 +4,10 @@ import chai from "chai"; import { BigNumber, Signer } from "ethers"; import { ethers } from "hardhat"; +import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../../helpers/deploymentConfig"; import { convertToUnit } from "../../../helpers/utils"; import { Comptroller, MockToken, PoolLens, PoolLens__factory, RewardsDistributor, VToken } from "../../../typechain"; +import { getDescription } from "../util/descriptionHelpers"; const { expect } = chai; chai.use(smock.matchers); @@ -25,6 +27,8 @@ let rewardToken3: FakeContract; let poolLens: MockContract; let account: Signer; let startBlock: number; +let isTimeBased = false; // for block based contracts +let blocksPerYear = BSC_BLOCKS_PER_YEAR; // for block based contracts type RewardsFixtire = { comptroller: FakeContract; @@ -51,7 +55,7 @@ const rewardsFixture = async (): Promise => { rewardToken2 = await smock.fake("MockToken"); rewardToken3 = await smock.fake("MockToken"); const poolLensFactory = await smock.mock("PoolLens"); - poolLens = await poolLensFactory.deploy(); + poolLens = await poolLensFactory.deploy(isTimeBased, blocksPerYear); const startBlock = await ethers.provider.getBlockNumber(); @@ -147,124 +151,249 @@ const rewardsFixture = async (): Promise => { }; }; -describe("PoolLens: Rewards Summary", () => { - beforeEach(async () => { - [account] = await ethers.getSigners(); - ({ - comptroller, - vBUSD, - vWBTC, - rewardDistributor1, - rewardToken1, - rewardDistributor2, - rewardToken2, - rewardDistributor3, - rewardToken3, - poolLens, - startBlock, - } = await loadFixture(rewardsFixture)); +const timeBasedRewardsFixture = async (): Promise => { + comptroller = await smock.fake("Comptroller"); + vBUSD = await smock.fake("VToken"); + vWBTC = await smock.fake("VToken"); + rewardDistributor1 = await smock.fake("RewardsDistributor"); + rewardDistributor2 = await smock.fake("RewardsDistributor"); + rewardDistributor3 = await smock.fake("RewardsDistributor"); + rewardToken1 = await smock.fake("MockToken"); + rewardToken2 = await smock.fake("MockToken"); + rewardToken3 = await smock.fake("MockToken"); + const poolLensFactory = await smock.mock("PoolLens"); + + isTimeBased = true; + blocksPerYear = SECONDS_PER_YEAR; + poolLens = await poolLensFactory.deploy(isTimeBased, blocksPerYear); + + const startBlock = (await ethers.provider.getBlock("latest")).number; + const startBlockTimestamp = (await ethers.provider.getBlock("latest")).timestamp; + + // Fake return values + comptroller.getAllMarkets.returns([vBUSD.address, vWBTC.address]); + comptroller.getRewardDistributors.returns([ + rewardDistributor1.address, + rewardDistributor2.address, + rewardDistributor3.address, + ]); + + rewardDistributor1.rewardToken.returns(rewardToken1.address); + rewardDistributor1.rewardTokenBorrowerIndex.returns(convertToUnit(1, 18)); + rewardDistributor1.rewardTokenSupplierIndex.returns(convertToUnit(1, 18)); + rewardDistributor1.rewardTokenAccrued.returns(convertToUnit(50, 18)); + rewardDistributor1.rewardTokenSupplySpeeds.whenCalledWith(vBUSD.address).returns(convertToUnit(0.5, 18)); + rewardDistributor1.rewardTokenSupplySpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); + rewardDistributor1.rewardTokenBorrowSpeeds.whenCalledWith(vBUSD.address).returns(convertToUnit(0.5, 18)); + rewardDistributor1.rewardTokenBorrowSpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); + rewardDistributor1.rewardTokenBorrowState.returns({ + index: convertToUnit(1, 18), + block: startBlockTimestamp, + lastRewardingBlock: 0, + }); + rewardDistributor1.rewardTokenSupplyState.returns({ + index: convertToUnit(1, 18), + block: startBlockTimestamp, + lastRewardingBlock: 0, }); - it("Should get summary for all markets", async () => { - // Mine some blocks so deltaBlocks != 0 - await mineUpTo(startBlock + 1000); + rewardDistributor2.rewardToken.returns(rewardToken2.address); + rewardDistributor2.rewardTokenBorrowerIndex.returns(convertToUnit(1, 18)); + rewardDistributor2.rewardTokenSupplierIndex.returns(convertToUnit(1, 18)); + rewardDistributor2.rewardTokenAccrued.returns(convertToUnit(50, 18)); + rewardDistributor2.rewardTokenSupplySpeeds.whenCalledWith(vBUSD.address).returns(convertToUnit(0.5, 18)); + rewardDistributor2.rewardTokenSupplySpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); + rewardDistributor2.rewardTokenBorrowSpeeds.whenCalledWith(vBUSD.address).returns(convertToUnit(0.5, 18)); + rewardDistributor2.rewardTokenBorrowSpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); + rewardDistributor2.rewardTokenBorrowState.returns({ + index: convertToUnit(1, 18), + block: startBlockTimestamp, + lastRewardingBlock: 0, + }); + rewardDistributor2.rewardTokenSupplyState.returns({ + index: convertToUnit(1, 18), + block: startBlockTimestamp, + lastRewardingBlock: 0, + }); - const accountAddress = await account.getAddress(); + rewardDistributor3.rewardToken.returns(rewardToken3.address); + rewardDistributor3.rewardTokenBorrowerIndex.returns(convertToUnit(1, 18)); + rewardDistributor3.rewardTokenSupplierIndex.returns(convertToUnit(1, 18)); + rewardDistributor3.rewardTokenAccrued.returns(convertToUnit(50, 18)); + rewardDistributor3.rewardTokenSupplySpeeds.whenCalledWith(vBUSD.address).returns(convertToUnit(0.5, 18)); + rewardDistributor3.rewardTokenSupplySpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); + rewardDistributor3.rewardTokenBorrowSpeeds.whenCalledWith(vBUSD.address).returns(convertToUnit(0.5, 18)); + rewardDistributor3.rewardTokenBorrowSpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); + rewardDistributor3.rewardTokenBorrowState.returns({ + index: convertToUnit(1, 18), + block: startBlockTimestamp, + lastRewardingBlock: 0, + }); + rewardDistributor3.rewardTokenSupplyState.returns({ + index: convertToUnit(1, 18), + block: startBlockTimestamp, + lastRewardingBlock: 0, + }); + + vBUSD.borrowIndex.returns(convertToUnit(1, 18)); + vBUSD.totalBorrows.returns(convertToUnit(10000, 8)); + vBUSD.totalSupply.returns(convertToUnit(10000, 8)); + vBUSD.balanceOf.returns(convertToUnit(100, 8)); + vBUSD.borrowBalanceStored.returns(convertToUnit(100, 8)); + + vWBTC.borrowIndex.returns(convertToUnit(1, 18)); + vWBTC.totalBorrows.returns(convertToUnit(100, 18)); + vWBTC.totalSupply.returns(convertToUnit(100, 18)); + vWBTC.balanceOf.returns(convertToUnit(100, 8)); + vWBTC.borrowBalanceStored.returns(convertToUnit(100, 8)); + + return { + comptroller, + vBUSD, + vWBTC, + rewardDistributor1, + rewardToken1, + rewardDistributor2, + rewardToken2, + rewardDistributor3, + rewardToken3, + poolLens, + startBlock, + }; +}; - const pendingRewards = await poolLens.getPendingRewards(accountAddress, comptroller.address); - expect(comptroller.getAllMarkets).to.have.been.calledOnce; - expect(comptroller.getRewardDistributors).to.have.been.calledOnce; +async function setup(isTimeBased: boolean) { + if (!isTimeBased) return await loadFixture(rewardsFixture); + return loadFixture(timeBasedRewardsFixture); +} - expect(rewardDistributor1.rewardToken).to.have.been.calledOnce; - expect(rewardDistributor2.rewardToken).to.have.been.calledOnce; - expect(rewardDistributor3.rewardToken).to.have.been.calledOnce; +for (const isTimeBased of [false, true]) { + const description = getDescription(isTimeBased); - expect(rewardDistributor1.rewardTokenAccrued).to.have.been.calledOnce; - expect(rewardDistributor2.rewardTokenAccrued).to.have.been.calledOnce; - expect(rewardDistributor3.rewardTokenAccrued).to.have.been.calledOnce; + describe(`${description}PoolLens: Rewards Summary`, () => { + beforeEach(async () => { + [account] = await ethers.getSigners(); + ({ + comptroller, + vBUSD, + vWBTC, + rewardDistributor1, + rewardToken1, + rewardDistributor2, + rewardToken2, + rewardDistributor3, + rewardToken3, + poolLens, + startBlock, + } = await setup(isTimeBased)); + }); - // Should be called once per market - expect(rewardDistributor1.rewardTokenBorrowState).to.have.been.callCount(2); - expect(rewardDistributor2.rewardTokenBorrowState).to.have.been.callCount(2); - expect(rewardDistributor3.rewardTokenBorrowState).to.have.been.callCount(2); + it("Should get summary for all markets", async () => { + // Mine some blocks so deltaBlocks != 0 + await mineUpTo(startBlock + 1000); - expect(rewardDistributor1.rewardTokenSupplyState).to.have.been.callCount(2); - expect(rewardDistributor2.rewardTokenSupplyState).to.have.been.callCount(2); - expect(rewardDistributor3.rewardTokenSupplyState).to.have.been.callCount(2); + const accountAddress = await account.getAddress(); - // Should be called once per reward token configured - expect(vBUSD.borrowIndex).to.have.been.callCount(3); - expect(vWBTC.borrowIndex).to.have.been.callCount(3); + const pendingRewards = await poolLens.getPendingRewards(accountAddress, comptroller.address); + expect(comptroller.getAllMarkets).to.have.been.calledOnce; + expect(comptroller.getRewardDistributors).to.have.been.calledOnce; - // Should be called once per reward token configured - expect(vBUSD.totalBorrows).to.have.been.callCount(3); - expect(vWBTC.totalSupply).to.have.been.callCount(3); + expect(rewardDistributor1.rewardToken).to.have.been.calledOnce; + expect(rewardDistributor2.rewardToken).to.have.been.calledOnce; + expect(rewardDistributor3.rewardToken).to.have.been.calledOnce; - const EXPECTED_OUTPUT = [ - [ - rewardDistributor1.address, - rewardToken1.address, - BigNumber.from(convertToUnit(50, 18)), + expect(rewardDistributor1.rewardTokenAccrued).to.have.been.calledOnce; + expect(rewardDistributor2.rewardTokenAccrued).to.have.been.calledOnce; + expect(rewardDistributor3.rewardTokenAccrued).to.have.been.calledOnce; + + // Should be called once per market + expect(rewardDistributor1.rewardTokenBorrowState).to.have.been.callCount(2); + expect(rewardDistributor2.rewardTokenBorrowState).to.have.been.callCount(2); + expect(rewardDistributor3.rewardTokenBorrowState).to.have.been.callCount(2); + + expect(rewardDistributor1.rewardTokenSupplyState).to.have.been.callCount(2); + expect(rewardDistributor2.rewardTokenSupplyState).to.have.been.callCount(2); + expect(rewardDistributor3.rewardTokenSupplyState).to.have.been.callCount(2); + + // Should be called once per reward token configured + expect(vBUSD.borrowIndex).to.have.been.callCount(3); + expect(vWBTC.borrowIndex).to.have.been.callCount(3); + + // Should be called once per reward token configured + expect(vBUSD.totalBorrows).to.have.been.callCount(3); + expect(vWBTC.totalSupply).to.have.been.callCount(3); + + const EXPECTED_OUTPUT = [ [ - [vBUSD.address, BigNumber.from(convertToUnit(10, 18))], - [vWBTC.address, BigNumber.from(convertToUnit(0.0000001, 18))], + rewardDistributor1.address, + rewardToken1.address, + BigNumber.from(convertToUnit(50, 18)), + [ + [vBUSD.address, BigNumber.from(convertToUnit(10, 18))], + [vWBTC.address, BigNumber.from(convertToUnit(0.0000001, 18))], + ], ], - ], - [ - rewardDistributor2.address, - rewardToken2.address, - BigNumber.from(convertToUnit(50, 18)), [ - [vBUSD.address, BigNumber.from(convertToUnit(10, 18))], - [vWBTC.address, BigNumber.from(convertToUnit(0.0000001, 18))], + rewardDistributor2.address, + rewardToken2.address, + BigNumber.from(convertToUnit(50, 18)), + [ + [vBUSD.address, BigNumber.from(convertToUnit(10, 18))], + [vWBTC.address, BigNumber.from(convertToUnit(0.0000001, 18))], + ], ], - ], - [ - rewardDistributor3.address, - rewardToken3.address, - BigNumber.from(convertToUnit(50, 18)), [ - [vBUSD.address, BigNumber.from(convertToUnit(10, 18))], - [vWBTC.address, BigNumber.from(convertToUnit(0.0000001, 18))], + rewardDistributor3.address, + rewardToken3.address, + BigNumber.from(convertToUnit(50, 18)), + [ + [vBUSD.address, BigNumber.from(convertToUnit(10, 18))], + [vWBTC.address, BigNumber.from(convertToUnit(0.0000001, 18))], + ], ], - ], - ]; - expect(pendingRewards).to.have.deep.members(EXPECTED_OUTPUT); - }); - - it("Should return accrued rewards if borrower borrowed before initialization", async () => { - comptroller.getRewardDistributors.returns([rewardDistributor3.address]); - rewardDistributor3.rewardTokenBorrowerIndex.returns(0); // Borrower borrowed before initialization, so they have no index - rewardDistributor3.rewardTokenBorrowState.returns({ - index: convertToUnit(1, 36), // Current index is 1.0, double scale - block: await ethers.provider.getBlockNumber(), - lastRewardingBlock: 0, + ]; + expect(pendingRewards).to.have.deep.members(EXPECTED_OUTPUT); }); - rewardDistributor3.INITIAL_INDEX.returns(convertToUnit(0.6, 36)); // Should start accruing rewards at 0.6 of the current index - - const pendingRewards = await poolLens.getPendingRewards(await account.getAddress(), comptroller.address); - - // The user has 0.000001% of the market share, and the reward accumulated since the beginning of the - // distribution is proportional to 1.0 (current index) - 0.6 (initial index) = 0.4. The index gets increased - // according to the configured distribution speed, so the speed is already included in the computation. - // The user should have accrued 0.000001% * 0.4 = 0.00000004 of the reward token (assuming the reward token - // has 18 decimals). - // - // Supplier reward is zero, because the global supply index is equal to the user's supply index, and there - // are no blocks between the last update and the current block. Thus, the results account only for the - // borrower reward. - - const EXPECTED_OUTPUT = [ - [ - rewardDistributor3.address, - rewardToken3.address, - BigNumber.from(convertToUnit(50, 18)), + + it("Should return accrued rewards if borrower borrowed before initialization", async () => { + comptroller.getRewardDistributors.returns([rewardDistributor3.address]); + rewardDistributor3.rewardTokenBorrowerIndex.returns(0); // Borrower borrowed before initialization, so they have no index + + let blockNumberOrTimestamp = (await ethers.provider.getBlock("latest")).number; + if (isTimeBased) { + blockNumberOrTimestamp = (await ethers.provider.getBlock("latest")).timestamp; + } + rewardDistributor3.rewardTokenBorrowState.returns({ + index: convertToUnit(1, 36), // Current index is 1.0, double scale + block: blockNumberOrTimestamp, + lastRewardingBlock: 0, + }); + rewardDistributor3.INITIAL_INDEX.returns(convertToUnit(0.6, 36)); // Should start accruing rewards at 0.6 of the current index + + const pendingRewards = await poolLens.getPendingRewards(await account.getAddress(), comptroller.address); + + // The user has 0.000001% of the market share, and the reward accumulated since the beginning of the + // distribution is proportional to 1.0 (current index) - 0.6 (initial index) = 0.4. The index gets increased + // according to the configured distribution speed, so the speed is already included in the computation. + // The user should have accrued 0.000001% * 0.4 = 0.00000004 of the reward token (assuming the reward token + // has 18 decimals). + // + // Supplier reward is zero, because the global supply index is equal to the user's supply index, and there + // are no blocks between the last update and the current block. Thus, the results account only for the + // borrower reward. + + const EXPECTED_OUTPUT = [ [ - [vBUSD.address, BigNumber.from(convertToUnit("0.000000004", 18))], - [vWBTC.address, BigNumber.from(convertToUnit("0.000000004", 18))], + rewardDistributor3.address, + rewardToken3.address, + BigNumber.from(convertToUnit(50, 18)), + [ + [vBUSD.address, BigNumber.from(convertToUnit("0.000000004", 18))], + [vWBTC.address, BigNumber.from(convertToUnit("0.000000004", 18))], + ], ], - ], - ]; - expect(pendingRewards).to.have.deep.members(EXPECTED_OUTPUT); + ]; + expect(pendingRewards).to.have.deep.members(EXPECTED_OUTPUT); + }); }); -}); +} diff --git a/tests/hardhat/Rewards.ts b/tests/hardhat/Rewards.ts index bf4e9b218..20b6062c6 100644 --- a/tests/hardhat/Rewards.ts +++ b/tests/hardhat/Rewards.ts @@ -5,6 +5,7 @@ import { expect } from "chai"; import { parseUnits } from "ethers/lib/utils"; import { ethers, upgrades } from "hardhat"; +import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; import { convertToUnit } from "../../helpers/utils"; import { AccessControlManager, @@ -19,6 +20,7 @@ import { VToken, } from "../../typechain"; import { deployVTokenBeacon, makeVToken } from "./util/TokenTestHelpers"; +import { getDescription } from "./util/descriptionHelpers"; // Disable a warning about mixing beacons and transparent proxies upgrades.silenceWarnings(); @@ -35,8 +37,9 @@ let xvs: MockToken; let fakePriceOracle: FakeContract; let fakeAccessControlManager: FakeContract; const maxLoopsLimit = 150; +let blocksPerYear = BSC_BLOCKS_PER_YEAR; // for block based contracts -async function rewardsFixture() { +async function rewardsFixture(isTimeBased: boolean) { [root] = await ethers.getSigners(); fakeAccessControlManager = await smock.fake("AccessControlManager"); @@ -95,14 +98,31 @@ async function rewardsFixture() { _minLiquidatableCollateral, ); + if (isTimeBased) { + blocksPerYear = SECONDS_PER_YEAR; + } + // Deploy VTokens - const vTokenBeacon = await deployVTokenBeacon(); + const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor"); + const vTokenBeacon = await deployVTokenBeacon(undefined, isTimeBased, blocksPerYear); vWBTC = await makeVToken({ underlying: mockWBTC, comptroller: comptrollerProxy, accessControlManager: fakeAccessControlManager, admin: root, beacon: vTokenBeacon, + isTimeBased: isTimeBased, + blocksPerYear: blocksPerYear, + }); + + vDAI = await makeVToken({ + underlying: mockDAI, + comptroller: comptrollerProxy, + accessControlManager: fakeAccessControlManager, + admin: root, + beacon: vTokenBeacon, + isTimeBased: isTimeBased, + blocksPerYear: blocksPerYear, }); const wbtcInitialSupply = parseUnits("10", 8); @@ -149,21 +169,17 @@ async function rewardsFixture() { xvs = await MockToken.deploy("Venus Token", "XVS", 18); // Configure rewards for pool - const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor"); - rewardsDistributor = (await upgrades.deployProxy(RewardsDistributor, [ - comptrollerProxy.address, - xvs.address, - maxLoopsLimit, - fakeAccessControlManager.address, - ])) as RewardsDistributor; - - const rewardsDistributor2 = await upgrades.deployProxy(RewardsDistributor, [ - comptrollerProxy.address, - mockDAI.address, - maxLoopsLimit, - fakeAccessControlManager.address, - ]); - + rewardsDistributor = (await upgrades.deployProxy( + RewardsDistributor, + [comptrollerProxy.address, xvs.address, maxLoopsLimit, fakeAccessControlManager.address], + { constructorArgs: [isTimeBased, blocksPerYear] }, + )) as RewardsDistributor; + + const rewardsDistributor2 = await upgrades.deployProxy( + RewardsDistributor, + [comptrollerProxy.address, mockDAI.address, maxLoopsLimit, fakeAccessControlManager.address], + { constructorArgs: [isTimeBased, blocksPerYear] }, + ); const initialXvs = convertToUnit(1000000, 18); await xvs.faucet(initialXvs); await xvs.transfer(rewardsDistributor.address, initialXvs); @@ -186,226 +202,283 @@ async function rewardsFixture() { ); } -describe("Rewards: Tests", async function () { - /** - * Deploying required contracts along with the poolRegistry. - */ - beforeEach(async function () { - await rewardsFixture(); - fakeAccessControlManager.isAllowedToCall.reset(); - fakeAccessControlManager.isAllowedToCall.returns(true); - }); - - it("Reverts if setting the speed is prohibited by ACM", async () => { - fakeAccessControlManager.isAllowedToCall - .whenCalledWith(root.address, "setRewardTokenSpeeds(address[],uint256[],uint256[])") - .returns(false); - await expect( - rewardsDistributor.setRewardTokenSpeeds( - [vWBTC.address, vDAI.address], - [convertToUnit(0.5, 18), convertToUnit(0.5, 18)], - [convertToUnit(0.5, 18), convertToUnit(0.5, 18)], - ), - ).to.be.revertedWithCustomError(rewardsDistributor, "Unauthorized"); - }); - - it("Should have correct btc balance", async function () { - const [owner] = await ethers.getSigners(); - - const btcBalance = await mockWBTC.balanceOf(owner.address); - - expect(btcBalance).equal(convertToUnit(1000, 8)); - }); - - it("Pool should have correct name", async function () { - // Get all pools list. - const pools = await poolRegistry.callStatic.getAllPools(); - expect(pools[0].name).equal("Pool 1"); - }); - - it("Rewards distributor should have correct balance", async function () { - expect(await xvs.balanceOf(rewardsDistributor.address)).equal(convertToUnit(1000000, 18)); - }); - - it("Should have correct market addresses", async function () { - const [owner] = await ethers.getSigners(); - - const res = await comptrollerProxy.getAssetsIn(owner.address); - expect(res[0]).equal(vDAI.address); - expect(res[1]).equal(vWBTC.address); - }); - - it("Comptroller returns correct reward speeds", async function () { - const res = await comptrollerProxy.getRewardsByMarket(vDAI.address); - expect(res[0][0]).equal(xvs.address); - expect(res[0][1].toString()).equal(convertToUnit(0.5, 18)); - expect(res[0][2].toString()).equal(convertToUnit(0.5, 18)); - expect(res[1][0]).equal(mockDAI.address); - expect(res[1][1].toString()).equal(convertToUnit(0.3, 18)); - expect(res[1][2].toString()).equal(convertToUnit(0.1, 18)); - }); - - it("Can add reward distributors with duplicate reward tokens", async function () { - const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor"); - rewardsDistributor = (await upgrades.deployProxy(RewardsDistributor, [ - comptrollerProxy.address, - xvs.address, - maxLoopsLimit, - fakeAccessControlManager.address, - ])) as RewardsDistributor; - - await expect(comptrollerProxy.addRewardsDistributor(rewardsDistributor.address)) - .to.emit(comptrollerProxy, "NewRewardsDistributor") - .withArgs(rewardsDistributor.address, xvs.address); - }); - - it("Emits event correctly", async () => { - const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor"); - rewardsDistributor = (await upgrades.deployProxy(RewardsDistributor, [ - comptrollerProxy.address, - mockWBTC.address, - maxLoopsLimit, - fakeAccessControlManager.address, - ])) as RewardsDistributor; - - await expect(comptrollerProxy.addRewardsDistributor(rewardsDistributor.address)) - .to.emit(comptrollerProxy, "NewRewardsDistributor") - .withArgs(rewardsDistributor.address, mockWBTC.address); - }); - - it("Claim XVS", async () => { - const [, user1, user2] = await ethers.getSigners(); - - await mockWBTC.connect(user1).faucet(convertToUnit(100, 8)); - await mockDAI.connect(user2).faucet(convertToUnit(10000, 18)); - - await mockWBTC.connect(user1).approve(vWBTC.address, convertToUnit(10, 8)); - await vWBTC.connect(user1).mint(convertToUnit(10, 8)); - - await rewardsDistributor.functions["claimRewardToken(address,address[])"](user1.address, [ - vWBTC.address, - vDAI.address, - ]); - - /* - Formula: (supplyIndex * supplyTokens * blocksDelta) + (borrowIndex * borrowTokens * blocksDelta) - 0.5 * 10 * 5 = 25 - */ - expect((await xvs.balanceOf(user1.address)).toString()).to.be.equal(convertToUnit(0.25, 18)); - - await mockDAI.connect(user2).approve(vDAI.address, convertToUnit(10000, 18)); - await vDAI.connect(user2).mint(convertToUnit(10000, 18)); - await vWBTC.connect(user2).borrow(convertToUnit(0.01, 8)); - - await rewardsDistributor["claimRewardToken(address,address[])"](user2.address, [vWBTC.address, vDAI.address]); - - expect((await xvs.balanceOf(user2.address)).toString()).to.be.equal(convertToUnit("1.40909090909090909", 18)); - }); - - it("Contributor Rewards", async () => { - const [, user1] = await ethers.getSigners(); - - expect((await xvs.balanceOf(user1.address)).toString()).to.be.equal("0"); - - await rewardsDistributor.setContributorRewardTokenSpeed(user1.address, convertToUnit(0.5, 18)); - - await mine(1000); - await rewardsDistributor.updateContributorRewards(user1.address); - - await rewardsDistributor["claimRewardToken(address,address[])"](user1.address, [vWBTC.address, vDAI.address]); - - /* - Formula: speed * blocks - 0.5 * 1001 = 500.5 - */ - expect((await xvs.balanceOf(user1.address)).toString()).be.equal(convertToUnit(500.5, 18)); - }); - - it("Multiple reward distributors with same reward token", async () => { - const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor"); - const newRewardsDistributor = (await upgrades.deployProxy(RewardsDistributor, [ - comptrollerProxy.address, - xvs.address, - maxLoopsLimit, - fakeAccessControlManager.address, - ])) as RewardsDistributor; - - await comptrollerProxy.addRewardsDistributor(newRewardsDistributor.address); - - const initialXvs = convertToUnit(1000000, 18); - await xvs.faucet(initialXvs); - await xvs.transfer(newRewardsDistributor.address, initialXvs); - - const [, user1] = await ethers.getSigners(); - - expect((await xvs.balanceOf(user1.address)).toString()).to.be.equal("0"); - - await rewardsDistributor.setContributorRewardTokenSpeed(user1.address, convertToUnit(0.5, 18)); - await newRewardsDistributor.setContributorRewardTokenSpeed(user1.address, convertToUnit(0.5, 18)); - - await mine(1000); - await rewardsDistributor.updateContributorRewards(user1.address); - await newRewardsDistributor.updateContributorRewards(user1.address); - - await rewardsDistributor["claimRewardToken(address,address[])"](user1.address, [vWBTC.address, vDAI.address]); - await newRewardsDistributor["claimRewardToken(address,address[])"](user1.address, [vWBTC.address, vDAI.address]); - - /* - Reward Distributor 1 - Formula: speed * blocks - 0.5 * 1001 = 500.5 - - Reward Distributor 2 - Formula: speed * blocks - 0.5 * 1003 = 501.5 - - Total xvs reward = 500.5 + 501.5 = 1002 - */ - expect((await xvs.balanceOf(user1.address)).toString()).be.equal(convertToUnit(1002, 18)); - }); - - it("pause rewards", async () => { - const [, user1, user2] = await ethers.getSigners(); +for (const isTimeBased of [false, true]) { + const description: string = getDescription(isTimeBased); + + describe(`${description}Rewards: Tests`, async function () { + /** + * Deploying required contracts along with the poolRegistry. + */ + beforeEach(async function () { + await rewardsFixture(isTimeBased); + fakeAccessControlManager.isAllowedToCall.reset(); + fakeAccessControlManager.isAllowedToCall.returns(true); + }); + + it("should revert when setting LastRewarding block or timestamp on invalid operation", async () => { + let lastRewardingBlockOrTimestamp; + if (!isTimeBased) { + lastRewardingBlockOrTimestamp = (await ethers.provider.getBlock("latest")).timestamp + 2; + + await expect( + rewardsDistributor.setLastRewardingBlockTimestamps( + [vWBTC.address, vDAI.address], + [lastRewardingBlockOrTimestamp - 10, lastRewardingBlockOrTimestamp - 10], + [lastRewardingBlockOrTimestamp - 10, lastRewardingBlockOrTimestamp - 10], + ), + ).to.be.revertedWith("Time-based operation only"); + } else { + lastRewardingBlockOrTimestamp = (await ethers.provider.getBlock("latest")).number + 2; + + await expect( + rewardsDistributor.setLastRewardingBlocks( + [vWBTC.address, vDAI.address], + [lastRewardingBlockOrTimestamp - 10, lastRewardingBlockOrTimestamp - 10], + [lastRewardingBlockOrTimestamp - 10, lastRewardingBlockOrTimestamp - 10], + ), + ).to.be.revertedWith("Block-based operation only"); + } + }); + + it("Reverts if setting the speed is prohibited by ACM", async () => { + fakeAccessControlManager.isAllowedToCall + .whenCalledWith(root.address, "setRewardTokenSpeeds(address[],uint256[],uint256[])") + .returns(false); + await expect( + rewardsDistributor.setRewardTokenSpeeds( + [vWBTC.address, vDAI.address], + [convertToUnit(0.5, 18), convertToUnit(0.5, 18)], + [convertToUnit(0.5, 18), convertToUnit(0.5, 18)], + ), + ).to.be.revertedWithCustomError(rewardsDistributor, "Unauthorized"); + }); + + it("Should have correct btc balance", async function () { + const [owner] = await ethers.getSigners(); + + const btcBalance = await mockWBTC.balanceOf(owner.address); + + expect(btcBalance).equal(convertToUnit(1000, 8)); + }); + + it("Pool should have correct name", async function () { + // Get all pools list. + const pools = await poolRegistry.callStatic.getAllPools(); + expect(pools[0].name).equal("Pool 1"); + }); + + it("Rewards distributor should have correct balance", async function () { + expect(await xvs.balanceOf(rewardsDistributor.address)).equal(convertToUnit(1000000, 18)); + }); + + it("Should have correct market addresses", async function () { + const [owner] = await ethers.getSigners(); + + const res = await comptrollerProxy.getAssetsIn(owner.address); + expect(res[0]).equal(vDAI.address); + expect(res[1]).equal(vWBTC.address); + }); + + it("Comptroller returns correct reward speeds", async function () { + const res = await comptrollerProxy.getRewardsByMarket(vDAI.address); + expect(res[0][0]).equal(xvs.address); + expect(res[0][1].toString()).equal(convertToUnit(0.5, 18)); + expect(res[0][2].toString()).equal(convertToUnit(0.5, 18)); + expect(res[1][0]).equal(mockDAI.address); + expect(res[1][1].toString()).equal(convertToUnit(0.3, 18)); + expect(res[1][2].toString()).equal(convertToUnit(0.1, 18)); + }); + + it("Can add reward distributors with duplicate reward tokens", async function () { + const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor"); + rewardsDistributor = (await upgrades.deployProxy( + RewardsDistributor, + [comptrollerProxy.address, xvs.address, maxLoopsLimit, fakeAccessControlManager.address], + { constructorArgs: [isTimeBased, blocksPerYear] }, + )) as RewardsDistributor; + + await expect(comptrollerProxy.addRewardsDistributor(rewardsDistributor.address)) + .to.emit(comptrollerProxy, "NewRewardsDistributor") + .withArgs(rewardsDistributor.address, xvs.address); + }); + + it("Emits event correctly", async () => { + const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor"); + rewardsDistributor = (await upgrades.deployProxy( + RewardsDistributor, + [comptrollerProxy.address, mockWBTC.address, maxLoopsLimit, fakeAccessControlManager.address], + { constructorArgs: [isTimeBased, blocksPerYear] }, + )) as RewardsDistributor; + + await expect(comptrollerProxy.addRewardsDistributor(rewardsDistributor.address)) + .to.emit(comptrollerProxy, "NewRewardsDistributor") + .withArgs(rewardsDistributor.address, mockWBTC.address); + }); + + it("Claim XVS", async () => { + const [, user1, user2] = await ethers.getSigners(); + + await mockWBTC.connect(user1).faucet(convertToUnit(100, 8)); + await mockDAI.connect(user2).faucet(convertToUnit(10000, 18)); + + await mockWBTC.connect(user1).approve(vWBTC.address, convertToUnit(10, 8)); + await vWBTC.connect(user1).mint(convertToUnit(10, 8)); + + await rewardsDistributor.functions["claimRewardToken(address,address[])"](user1.address, [ + vWBTC.address, + vDAI.address, + ]); + + /* + Formula: (supplyIndex * supplyTokens * blocksDelta) + (borrowIndex * borrowTokens * blocksDelta) + 0.5 * 10 * 5 = 25 + */ + expect((await xvs.balanceOf(user1.address)).toString()).to.be.equal(convertToUnit(0.25, 18)); + + await mockDAI.connect(user2).approve(vDAI.address, convertToUnit(10000, 18)); + await vDAI.connect(user2).mint(convertToUnit(10000, 18)); + await vWBTC.connect(user2).borrow(convertToUnit(0.01, 8)); + + await rewardsDistributor["claimRewardToken(address,address[])"](user2.address, [vWBTC.address, vDAI.address]); + + expect((await xvs.balanceOf(user2.address)).toString()).to.be.equal(convertToUnit("1.40909090909090909", 18)); + }); + + it("Contributor Rewards", async () => { + const [, user1] = await ethers.getSigners(); + + expect((await xvs.balanceOf(user1.address)).toString()).to.be.equal("0"); + + await rewardsDistributor.setContributorRewardTokenSpeed(user1.address, convertToUnit(0.5, 18)); + + await mine(1000); + await rewardsDistributor.updateContributorRewards(user1.address); + + await rewardsDistributor["claimRewardToken(address,address[])"](user1.address, [vWBTC.address, vDAI.address]); + + /* + Formula: speed * blocks + 0.5 * 1001 = 500.5 + */ + expect((await xvs.balanceOf(user1.address)).toString()).be.equal(convertToUnit(500.5, 18)); + }); + + it("Multiple reward distributors with same reward token", async () => { + const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor"); + const newRewardsDistributor = (await upgrades.deployProxy( + RewardsDistributor, + [comptrollerProxy.address, xvs.address, maxLoopsLimit, fakeAccessControlManager.address], + { constructorArgs: [isTimeBased, blocksPerYear] }, + )) as RewardsDistributor; + + await comptrollerProxy.addRewardsDistributor(newRewardsDistributor.address); + + const initialXvs = convertToUnit(1000000, 18); + await xvs.faucet(initialXvs); + await xvs.transfer(newRewardsDistributor.address, initialXvs); + + const [, user1] = await ethers.getSigners(); + + expect((await xvs.balanceOf(user1.address)).toString()).to.be.equal("0"); + + await rewardsDistributor.setContributorRewardTokenSpeed(user1.address, convertToUnit(0.5, 18)); + await newRewardsDistributor.setContributorRewardTokenSpeed(user1.address, convertToUnit(0.5, 18)); + + await mine(1000); + await rewardsDistributor.updateContributorRewards(user1.address); + await newRewardsDistributor.updateContributorRewards(user1.address); + + await rewardsDistributor["claimRewardToken(address,address[])"](user1.address, [vWBTC.address, vDAI.address]); + await newRewardsDistributor["claimRewardToken(address,address[])"](user1.address, [vWBTC.address, vDAI.address]); + + /* + Reward Distributor 1 + Formula: speed * blocks + 0.5 * 1001 = 500.5 + + Reward Distributor 2 + Formula: speed * blocks + 0.5 * 1003 = 501.5 + + Total xvs reward = 500.5 + 501.5 = 1002 + */ + expect((await xvs.balanceOf(user1.address)).toString()).be.equal(convertToUnit(1002, 18)); + }); - await mockWBTC.connect(user1).faucet(convertToUnit(100, 8)); - await mockDAI.connect(user2).faucet(convertToUnit(10000, 18)); + it("pause rewards", async () => { + const [, user1, user2] = await ethers.getSigners(); - await mockWBTC.connect(user1).approve(vWBTC.address, convertToUnit(10, 8)); - await vWBTC.connect(user1).mint(convertToUnit(10, 8)); + await mockWBTC.connect(user1).faucet(convertToUnit(100, 8)); + await mockDAI.connect(user2).faucet(convertToUnit(10000, 18)); - let lastRewardingBlock = (await ethers.provider.getBlockNumber()) + 2; + await mockWBTC.connect(user1).approve(vWBTC.address, convertToUnit(10, 8)); + await vWBTC.connect(user1).mint(convertToUnit(10, 8)); - await rewardsDistributor.setLastRewardingBlocks( - [vWBTC.address, vDAI.address], - [lastRewardingBlock, lastRewardingBlock], - [lastRewardingBlock, lastRewardingBlock], - ); + let lastRewardingBlockOrTimestamp = (await ethers.provider.getBlock("latest")).number + 2; + if (isTimeBased) { + lastRewardingBlockOrTimestamp = (await ethers.provider.getBlock("latest")).timestamp + 2; + } - await mine(100); + if (!isTimeBased) { + await rewardsDistributor.setLastRewardingBlocks( + [vWBTC.address, vDAI.address], + [lastRewardingBlockOrTimestamp, lastRewardingBlockOrTimestamp], + [lastRewardingBlockOrTimestamp, lastRewardingBlockOrTimestamp], + ); + } else { + await rewardsDistributor.setLastRewardingBlockTimestamps( + [vWBTC.address, vDAI.address], + [lastRewardingBlockOrTimestamp, lastRewardingBlockOrTimestamp], + [lastRewardingBlockOrTimestamp, lastRewardingBlockOrTimestamp], + ); + } - await rewardsDistributor.functions["claimRewardToken(address,address[])"](user1.address, [ - vWBTC.address, - vDAI.address, - ]); + await mine(100); - expect((await xvs.balanceOf(user1.address)).toString()).to.be.equal(convertToUnit(0.5, 18)); + await rewardsDistributor.functions["claimRewardToken(address,address[])"](user1.address, [ + vWBTC.address, + vDAI.address, + ]); - await expect( - rewardsDistributor.setLastRewardingBlocks( - [vWBTC.address, vDAI.address], - [lastRewardingBlock - 10, lastRewardingBlock - 10], - [lastRewardingBlock - 10, lastRewardingBlock - 10], - ), - ).to.be.revertedWith("setting last rewarding block in the past is not allowed"); + expect((await xvs.balanceOf(user1.address)).toString()).to.be.equal(convertToUnit(0.5, 18)); - lastRewardingBlock = (await ethers.provider.getBlockNumber()) + 2; + if (!isTimeBased) { + await expect( + rewardsDistributor.setLastRewardingBlocks( + [vWBTC.address, vDAI.address], + [lastRewardingBlockOrTimestamp - 10, lastRewardingBlockOrTimestamp - 10], + [lastRewardingBlockOrTimestamp - 10, lastRewardingBlockOrTimestamp - 10], + ), + ).to.be.revertedWith("setting last rewarding block in the past is not allowed"); + } else { + await expect( + rewardsDistributor.setLastRewardingBlockTimestamps( + [vWBTC.address, vDAI.address], + [lastRewardingBlockOrTimestamp - 10, lastRewardingBlockOrTimestamp - 10], + [lastRewardingBlockOrTimestamp - 10, lastRewardingBlockOrTimestamp - 10], + ), + ).to.be.revertedWith("setting last rewarding timestamp in the past is not allowed"); + } - await expect( - rewardsDistributor.setLastRewardingBlocks( - [vWBTC.address, vDAI.address], - [lastRewardingBlock, lastRewardingBlock], - [lastRewardingBlock, lastRewardingBlock], - ), - ).to.be.revertedWith("this RewardsDistributor is already locked"); + if (!isTimeBased) { + lastRewardingBlockOrTimestamp = (await ethers.provider.getBlock("latest")).number + 2; + await expect( + rewardsDistributor.setLastRewardingBlocks( + [vWBTC.address, vDAI.address], + [lastRewardingBlockOrTimestamp, lastRewardingBlockOrTimestamp], + [lastRewardingBlockOrTimestamp, lastRewardingBlockOrTimestamp], + ), + ).to.be.revertedWith("this RewardsDistributor is already locked"); + } else { + lastRewardingBlockOrTimestamp = (await ethers.provider.getBlock("latest")).timestamp + 2; + await expect( + rewardsDistributor.setLastRewardingBlockTimestamps( + [vWBTC.address, vDAI.address], + [lastRewardingBlockOrTimestamp, lastRewardingBlockOrTimestamp], + [lastRewardingBlockOrTimestamp, lastRewardingBlockOrTimestamp], + ), + ).to.be.revertedWith("this RewardsDistributor is already locked"); + } + }); }); -}); +} diff --git a/tests/hardhat/Shortfall.ts b/tests/hardhat/Shortfall.ts index 01033328b..2952333a6 100644 --- a/tests/hardhat/Shortfall.ts +++ b/tests/hardhat/Shortfall.ts @@ -7,6 +7,7 @@ import { constants } from "ethers"; import { parseUnits } from "ethers/lib/utils"; import { ethers, upgrades } from "hardhat"; +import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; import { AddressOne, convertToUnit } from "../../helpers/utils"; import { AccessControlManager, @@ -22,6 +23,7 @@ import { VToken, VToken__factory, } from "../../typechain"; +import { getDescription } from "./util/descriptionHelpers"; const { expect } = chai; chai.use(smock.matchers); @@ -44,8 +46,10 @@ let vFloki: MockContract; let comptroller: FakeContract; let fakePriceOracle: FakeContract; -let riskFundBalance = "10000"; +const riskFundBalance = "10000"; const minimumPoolBadDebt = "10000"; +let isTimeBased = false; // for block based contracts +let blocksPerYear = BSC_BLOCKS_PER_YEAR; // for block based contracts let poolAddress; /** @@ -61,11 +65,11 @@ async function shortfallFixture() { fakeRiskFund = await smock.fake("IRiskFund"); const Shortfall = await smock.mock("Shortfall"); - shortfall = await upgrades.deployProxy(Shortfall, [ - fakeRiskFund.address, - parseUnits(minimumPoolBadDebt, "18"), - accessControlManager.address, - ]); + shortfall = await upgrades.deployProxy( + Shortfall, + [fakeRiskFund.address, parseUnits(minimumPoolBadDebt, "18"), accessControlManager.address], + { constructorArgs: [isTimeBased, blocksPerYear] }, + ); [owner, someone, bidder1, bidder2] = await ethers.getSigners(); @@ -98,9 +102,9 @@ async function shortfallFixture() { }); const VToken = await smock.mock("VToken"); - vDAI = await VToken.deploy(); - vWBTC = await VToken.deploy(); - vFloki = await VToken.deploy(); + vDAI = await VToken.deploy(isTimeBased, blocksPerYear); + vWBTC = await VToken.deploy(isTimeBased, blocksPerYear); + vFloki = await VToken.deploy(isTimeBased, blocksPerYear); await vWBTC.setVariable("decimals", 8); vDAI.decimals.returns(18); @@ -177,634 +181,811 @@ async function shortfallFixture() { await mockFloki.connect(bidder2).approve(shortfall.address, parseUnits("150", 18)); } -async function setup() { - await loadFixture(shortfallFixture); -} +async function timeBasedhortfallFixture() { + isTimeBased = true; + blocksPerYear = SECONDS_PER_YEAR; + const MockBUSD = await ethers.getContractFactory("MockToken"); + mockBUSD = await MockBUSD.deploy("BUSD", "BUSD", 18); + await mockBUSD.faucet(convertToUnit(100000, 18)); -describe("Shortfall: Tests", async function () { - describe("setters", async function () { - beforeEach(setup); + const AccessControlManagerFactor = await ethers.getContractFactory("AccessControlManager"); + accessControlManager = await AccessControlManagerFactor.deploy(); + fakeRiskFund = await smock.fake("IRiskFund"); - describe("updatePoolRegistry", async function () { - it("reverts on invalid PoolRegistry address", async function () { - await expect(shortfall.updatePoolRegistry(constants.AddressZero)).to.be.revertedWithCustomError( - shortfall, - "ZeroAddressNotAllowed", - ); - }); + const Shortfall = await smock.mock("Shortfall"); + shortfall = await upgrades.deployProxy( + Shortfall, + [fakeRiskFund.address, parseUnits(minimumPoolBadDebt, "18"), accessControlManager.address], + { + constructorArgs: [isTimeBased, blocksPerYear], + }, + ); + [owner, someone, bidder1, bidder2] = await ethers.getSigners(); - it("fails if called by a non-owner", async function () { - await expect(shortfall.connect(someone).updatePoolRegistry(poolRegistry.address)).to.be.rejectedWith( - "Ownable: caller is not the owner", - ); - }); + poolRegistry = await smock.fake("PoolRegistry"); - it("emits PoolRegistryUpdated event", async function () { - const tx = shortfall.updatePoolRegistry(someone.address); - await expect(tx).to.emit(shortfall, "PoolRegistryUpdated").withArgs(poolRegistry.address, someone.address); - }); - }); + await shortfall.updatePoolRegistry(poolRegistry.address); - describe("updateMinimumPoolBadDebt", async function () { - it("fails if called by a non permissioned account", async function () { - await expect(shortfall.connect(someone).updateMinimumPoolBadDebt(1)).to.be.reverted; - }); + // Deploy Mock Tokens + const MockDAI = await ethers.getContractFactory("MockToken"); + mockDAI = await MockDAI.deploy("MakerDAO", "DAI", 18); + await mockDAI.faucet(convertToUnit(1000000000, 18)); - it("updates minimumPoolBadDebt in storage", async function () { - await shortfall.updateMinimumPoolBadDebt(1); - expect(await shortfall.minimumPoolBadDebt()).to.equal(1); - }); + const MockWBTC = await ethers.getContractFactory("MockToken"); + mockWBTC = await MockWBTC.deploy("Bitcoin", "BTC", 8); + await mockWBTC.faucet(convertToUnit(1000000000, 8)); - it("emits MinimumPoolBadDebtUpdated event", async function () { - const tx = shortfall.updateMinimumPoolBadDebt(1); - await expect(tx) - .to.emit(shortfall, "MinimumPoolBadDebtUpdated") - .withArgs(parseUnits(minimumPoolBadDebt, "18"), 1); - }); - }); + const MockFloki = await ethers.getContractFactory("MockDeflatingToken"); + mockFloki = await MockFloki.deploy(convertToUnit(1000000000, 18)); - describe("waitForFirstBidder", async function () { - it("fails if called by a non permissioned account", async function () { - await expect(shortfall.connect(someone).updateWaitForFirstBidder(200)).to.be.reverted; - }); + const Comptroller = await smock.mock("Comptroller"); + comptroller = await Comptroller.deploy(poolRegistry.address); + poolAddress = comptroller.address; - it("updates updateWaitForFirstBidder in storage", async function () { - await shortfall.updateWaitForFirstBidder(200); - expect(await shortfall.waitForFirstBidder()).to.equal(200); - }); + poolRegistry.getPoolByComptroller.returns({ + name: "test", + creator: AddressOne, + comptroller: comptroller.address, + blockPosted: 0, + timestampPosted: 0, + }); - it("emits WaitForFirstBidderUpdated event", async function () { - const tx = shortfall.updateWaitForFirstBidder(200); - await expect(tx).to.emit(shortfall, "WaitForFirstBidderUpdated").withArgs(100, 200); - }); - }); + const VToken = await smock.mock("VToken"); + vDAI = await VToken.deploy(isTimeBased, blocksPerYear); + vWBTC = await VToken.deploy(isTimeBased, blocksPerYear); + vFloki = await VToken.deploy(isTimeBased, blocksPerYear); - describe("updateNextBidderBlockLimit", async function () { - it("fails if called by a non permissioned account", async function () { - await accessControlManager.revokeCallPermission( - shortfall.address, - "updateNextBidderBlockLimit(uint256)", - owner.address, - ); - await expect(shortfall.connect(someone).updateNextBidderBlockLimit(1)).to.be.reverted; - await accessControlManager.giveCallPermission( - shortfall.address, - "updateNextBidderBlockLimit(uint256)", - owner.address, - ); - }); + await vWBTC.setVariable("decimals", 8); + vDAI.decimals.returns(18); - it("updates nextBidderBlockLimit in storage", async function () { - await shortfall.updateNextBidderBlockLimit(100); - expect(await shortfall.nextBidderBlockLimit()).to.equal(100); - }); + vDAI.underlying.returns(mockDAI.address); + fakeRiskFund.convertibleBaseAsset.returns(mockDAI.address); + await vWBTC.setVariable("underlying", mockWBTC.address); + await vFloki.setVariable("underlying", mockFloki.address); - it("emits NextBidderBlockLimitUpdated event", async function () { - const tx = shortfall.updateNextBidderBlockLimit(110); - await expect(tx).to.emit(shortfall, "NextBidderBlockLimitUpdated").withArgs(100, 110); - }); - }); + await vDAI.setVariable("shortfall", shortfall.address); + await vWBTC.setVariable("shortfall", shortfall.address); + await vFloki.setVariable("shortfall", shortfall.address); + + comptroller.getAllMarkets.returns(() => { + return [vDAI.address, vWBTC.address, vFloki.address]; }); - describe("updateIncentiveBps", async function () { - it("fails if caller is not allowed", async function () { - await expect(shortfall.connect(someone).updateIncentiveBps(1)).to.be.reverted; - }); + fakePriceOracle = await smock.fake("ResilientOracleInterface"); - it("fails if new incentive BPS is set to 0", async function () { - await expect(shortfall.updateIncentiveBps(0)).to.be.revertedWith("incentiveBps must not be 0"); - }); + const btcPrice = "21000.34"; + const daiPrice = "1"; - it("emits IncentiveBpsUpdated event", async function () { - const tx = shortfall.updateIncentiveBps(2000); - await expect(tx).to.emit(shortfall, "IncentiveBpsUpdated").withArgs(1000, 2000); - }); + fakePriceOracle.getUnderlyingPrice.returns((args: any) => { + if (vDAI && vWBTC && vFloki) { + if (args[0] === vDAI.address) { + return convertToUnit(daiPrice, 18); + } else if (args[0] === vWBTC.address) { + return convertToUnit(btcPrice, 28); + } else { + return convertToUnit(1, 18); + } + } + + return convertToUnit(1, 18); }); - describe("placeBid", async function () { - beforeEach(setup); - let auctionStartBlock; + fakePriceOracle.getPrice.whenCalledWith(mockDAI.address).returns(convertToUnit(1, 18)); - async function startAuction() { - vDAI.badDebt.returns(parseUnits("10000", 18)); - await vDAI.setVariable("badDebt", parseUnits("10000", 18)); - vWBTC.badDebt.returns(parseUnits("2", 8)); - await vWBTC.setVariable("badDebt", parseUnits("2", 8)); - await shortfall.startAuction(poolAddress); - const auction = await shortfall.auctions(poolAddress); - auctionStartBlock = auction.startBlock; - } + comptroller.oracle.returns(fakePriceOracle.address); - it("fails if auction is not active", async function () { - await expect(shortfall.placeBid(poolAddress, "10000", 0)).to.be.revertedWith("no on-going auction"); - }); + fakeRiskFund.getPoolsBaseAssetReserves.returns(parseUnits(riskFundBalance, 18)); - it("fails if auction is stale", async function () { - await startAuction(); - await mine(100); - await expect(shortfall.placeBid(poolAddress, "10000", auctionStartBlock)).to.be.revertedWith( - "auction is stale, restart it", - ); - }); + // Access Control + await accessControlManager.giveCallPermission(shortfall.address, "updateIncentiveBps(uint256)", owner.address); - it("fails if bidBps is zero", async () => { - await startAuction(); - await expect(shortfall.placeBid(poolAddress, "0", auctionStartBlock)).to.be.revertedWith( - "basis points cannot be zero", - ); - }); + await accessControlManager.giveCallPermission(shortfall.address, "updateMinimumPoolBadDebt(uint256)", owner.address); - it("fails if auctionStartBlock does not match the auction startBlock", async () => { - await startAuction(); - await mine(10); - const latestBlock = await ethers.provider.getBlock("latest"); - await expect(shortfall.placeBid(poolAddress, "0", latestBlock.number)).to.be.revertedWith( - "auction has been restarted", - ); - }); - }); + await accessControlManager.giveCallPermission(shortfall.address, "updateWaitForFirstBidder(uint256)", owner.address); - describe("LARGE_POOL_DEBT Scenario", async function () { - before(setup); - let startBlockNumber; + await accessControlManager.giveCallPermission(shortfall.address, "pauseAuctions()", owner.address); - it("Should have debt and reserve", async function () { - vDAI.badDebt.returns(parseUnits("1000", 18)); - vWBTC.badDebt.returns(parseUnits("1", 8)); + await accessControlManager.giveCallPermission(shortfall.address, "resumeAuctions()", owner.address); - expect(await fakeRiskFund.getPoolsBaseAssetReserves(comptroller.address)).equal( - parseUnits(riskFundBalance, 18).toString(), - ); + await accessControlManager.giveCallPermission( + shortfall.address, + "updateNextBidderBlockLimit(uint256)", + owner.address, + ); - expect(await vDAI.badDebt()).equal(parseUnits("1000", 18)); - expect(await vWBTC.badDebt()).equal(parseUnits("1", 8)); - }); + // setup bidders + // bidder 1 + await mockDAI.transfer(bidder1.address, parseUnits("500000", 18)); + await mockDAI.connect(bidder1).approve(shortfall.address, parseUnits("100000", 18)); + await mockWBTC.transfer(bidder1.address, parseUnits("50", 8)); + await mockWBTC.connect(bidder1).approve(shortfall.address, parseUnits("50", 8)); + await mockFloki.connect(owner).transfer(bidder1.address, parseUnits("200", 18)); + await mockFloki.connect(bidder1).approve(shortfall.address, parseUnits("150", 18)); + // // bidder 2 + await mockDAI.transfer(bidder2.address, parseUnits("500000", 18)); + await mockDAI.connect(bidder2).approve(shortfall.address, parseUnits("100000", 18)); + await mockWBTC.transfer(bidder2.address, parseUnits("50", 8)); + await mockWBTC.connect(bidder2).approve(shortfall.address, parseUnits("50", 8)); + await mockFloki.connect(owner).transfer(bidder2.address, parseUnits("200", 18)); + await mockFloki.connect(bidder2).approve(shortfall.address, parseUnits("150", 18)); +} - it("Should not be able to start auction when bad debt is low", async function () { - vDAI.badDebt.returns(parseUnits("20", 18)); - vWBTC.badDebt.returns(parseUnits("0.01", 8)); +async function setup(isTimeBased: boolean) { + if (!isTimeBased) { + await loadFixture(shortfallFixture); + return; + } + await loadFixture(timeBasedhortfallFixture); +} - await expect(shortfall.startAuction(poolAddress)).to.be.revertedWith("pool bad debt is too low"); - }); +for (const isTimeBased of [false, true]) { + const description: string = getDescription(isTimeBased); - it("can't restart when there is no ongoing auction", async function () { - await expect(shortfall.restartAuction(poolAddress)).to.be.revertedWith("no on-going auction"); - }); + describe(`${description}Shortfall: Tests`, async function () { + describe("setters", async function () { + beforeEach(async function () { + await setup(isTimeBased); + }); + + describe("updatePoolRegistry", async function () { + it("reverts on invalid PoolRegistry address", async function () { + await expect(shortfall.updatePoolRegistry(constants.AddressZero)).to.be.revertedWithCustomError( + shortfall, + "ZeroAddressNotAllowed", + ); + }); + + it("fails if called by a non-owner", async function () { + await expect(shortfall.connect(someone).updatePoolRegistry(poolRegistry.address)).to.be.rejectedWith( + "Ownable: caller is not the owner", + ); + }); + + it("emits PoolRegistryUpdated event", async function () { + const tx = shortfall.updatePoolRegistry(someone.address); + await expect(tx).to.emit(shortfall, "PoolRegistryUpdated").withArgs(poolRegistry.address, someone.address); + }); + }); + + describe("updateMinimumPoolBadDebt", async function () { + it("fails if called by a non permissioned account", async function () { + await expect(shortfall.connect(someone).updateMinimumPoolBadDebt(1)).to.be.reverted; + }); + + it("updates minimumPoolBadDebt in storage", async function () { + await shortfall.updateMinimumPoolBadDebt(1); + expect(await shortfall.minimumPoolBadDebt()).to.equal(1); + }); + + it("emits MinimumPoolBadDebtUpdated event", async function () { + const tx = shortfall.updateMinimumPoolBadDebt(1); + await expect(tx) + .to.emit(shortfall, "MinimumPoolBadDebtUpdated") + .withArgs(parseUnits(minimumPoolBadDebt, "18"), 1); + }); + }); - it("Should not be able to close auction when there is no active auction", async function () { - await expect(shortfall.closeAuction(poolAddress)).to.be.revertedWith("no on-going auction"); + describe("waitForFirstBidder", async function () { + it("fails if called by a non permissioned account", async function () { + await expect(shortfall.connect(someone).updateWaitForFirstBidder(200)).to.be.reverted; + }); + + it("updates updateWaitForFirstBidder in storage", async function () { + await shortfall.updateWaitForFirstBidder(200); + expect(await shortfall.waitForFirstBidder()).to.equal(200); + }); + + it("emits WaitForFirstBidderUpdated event", async function () { + const tx = shortfall.updateWaitForFirstBidder(200); + if (!isTimeBased) { + await expect(tx).to.emit(shortfall, "WaitForFirstBidderUpdated").withArgs(100, 200); + } else { + await expect(tx).to.emit(shortfall, "WaitForFirstBidderUpdated").withArgs(300, 200); + } + }); + }); + + describe("updateNextBidderBlockLimit", async function () { + it("fails if called by a non permissioned account", async function () { + await accessControlManager.revokeCallPermission( + shortfall.address, + "updateNextBidderBlockLimit(uint256)", + owner.address, + ); + await expect(shortfall.connect(someone).updateNextBidderBlockLimit(1)).to.be.reverted; + await accessControlManager.giveCallPermission( + shortfall.address, + "updateNextBidderBlockLimit(uint256)", + owner.address, + ); + }); + + it("updates nextBidderBlockLimit in storage", async function () { + await shortfall.updateNextBidderBlockLimit(100); + expect(await shortfall.nextBidderBlockLimit()).to.equal(100); + }); + + it("emits NextBidderBlockLimitUpdated event", async function () { + const tx = shortfall.updateNextBidderBlockLimit(110); + if (!isTimeBased) { + await expect(tx).to.emit(shortfall, "NextBidderBlockLimitUpdated").withArgs(100, 110); + } else { + await expect(tx).to.emit(shortfall, "NextBidderBlockLimitUpdated").withArgs(300, 110); + } + }); + }); }); - it("Should not be able to placeBid when there is no active auction", async function () { - vDAI.badDebt.returns(parseUnits("20", 18)); - vWBTC.badDebt.returns(parseUnits("0.01", 8)); - const auction = await shortfall.auctions(poolAddress); + describe("updateIncentiveBps", async function () { + it("fails if caller is not allowed", async function () { + await expect(shortfall.connect(someone).updateIncentiveBps(1)).to.be.reverted; + }); - await expect(shortfall.placeBid(poolAddress, "1800", auction.startBlock)).to.be.revertedWith( - "no on-going auction", - ); + it("fails if new incentive BPS is set to 0", async function () { + await expect(shortfall.updateIncentiveBps(0)).to.be.revertedWith("incentiveBps must not be 0"); + }); + + it("emits IncentiveBpsUpdated event", async function () { + const tx = shortfall.updateIncentiveBps(2000); + await expect(tx).to.emit(shortfall, "IncentiveBpsUpdated").withArgs(1000, 2000); + }); }); - it("Start auction", async function () { - vDAI.badDebt.returns(parseUnits("10000", 18)); - await vDAI.setVariable("badDebt", parseUnits("10000", 18)); - vWBTC.badDebt.returns(parseUnits("2", 8)); - await vWBTC.setVariable("badDebt", parseUnits("2", 8)); + describe("placeBid", async function () { + beforeEach(async function () { + await setup(isTimeBased); + }); + let auctionStartBlock; + + async function startAuction() { + vDAI.badDebt.returns(parseUnits("10000", 18)); + await vDAI.setVariable("badDebt", parseUnits("10000", 18)); + vWBTC.badDebt.returns(parseUnits("2", 8)); + await vWBTC.setVariable("badDebt", parseUnits("2", 8)); + await shortfall.startAuction(poolAddress); + const auction = await shortfall.auctions(poolAddress); + auctionStartBlock = auction.startBlockOrTimestamp; + } - const receipt = await shortfall.startAuction(poolAddress); - startBlockNumber = receipt.blockNumber; + it("fails if auction is not active", async function () { + await expect(shortfall.placeBid(poolAddress, "10000", 0)).to.be.revertedWith("no on-going auction"); + }); - const auction = await shortfall.auctions(poolAddress); + it("fails if auction is stale", async function () { + await startAuction(); + if (!isTimeBased) { + await mine(100); + } else { + await mine(300); + } + await expect(shortfall.placeBid(poolAddress, "10000", auctionStartBlock)).to.be.revertedWith( + "auction is stale, restart it", + ); + }); - expect(auction.status).equal(1); - expect(auction.auctionType).equal(0); - expect(auction.seizedRiskFund).equal(parseUnits(riskFundBalance, 18)); + it("fails if bidBps is zero", async () => { + await startAuction(); + await expect(shortfall.placeBid(poolAddress, "0", auctionStartBlock)).to.be.revertedWith( + "basis points cannot be zero", + ); + }); - const startBidBps = new BigNumber("10000000000").dividedBy("52000.68").dividedBy("11000").toFixed(2); - expect(auction.startBidBps.toString()).equal(new BigNumber(startBidBps).times(100).toString()); + it("fails if auctionStartBlock does not match the auction startBlock", async () => { + await startAuction(); + await mine(10); + let latestBlockOrTimestamp = (await ethers.provider.getBlock("latest")).number; + if (isTimeBased) { + latestBlockOrTimestamp = (await ethers.provider.getBlock("latest")).timestamp; + } + await expect(shortfall.placeBid(poolAddress, "0", latestBlockOrTimestamp)).to.be.revertedWith( + "auction has been restarted", + ); + }); }); - it("Should not be able to place bid lower max basis points", async function () { - const auction = await shortfall.auctions(poolAddress); - await expect(shortfall.placeBid(poolAddress, "10001", auction.startBlock)).to.be.revertedWith( - "basis points cannot be more than 10000", - ); - }); + describe("LARGE_POOL_DEBT Scenario", async function () { + before(async function () { + await setup(isTimeBased); + }); + let startBlockNumber; - it("Place bid", async function () { - const auction = await shortfall.auctions(poolAddress); + it("Should have debt and reserve", async function () { + vDAI.badDebt.returns(parseUnits("1000", 18)); + vWBTC.badDebt.returns(parseUnits("1", 8)); - await mockDAI.approve(shortfall.address, parseUnits("10000", 18)); - await mockWBTC.approve(shortfall.address, parseUnits("2", 8)); - - const previousDaiBalance = await mockDAI.balanceOf(owner.address); - const previousWBTCBalance = await mockWBTC.balanceOf(owner.address); - - await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlock); - expect((await mockDAI.balanceOf(owner.address)).div(parseUnits("1", 18)).toNumber()).lt( - previousDaiBalance.div(parseUnits("1", 18)).toNumber(), - ); - expect((await mockWBTC.balanceOf(owner.address)).div(parseUnits("1", 8)).toNumber()).lt( - previousWBTCBalance.div(parseUnits("1", 8)).toNumber(), - ); - - let percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); - let total = new BigNumber((await vDAI.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); - let amountToDeduct = new BigNumber(total).times(percentageToDeduct).dividedBy(100).toString(); - let amountDeducted = new BigNumber(previousDaiBalance.div(parseUnits("1", 18)).toString()) - .minus((await mockDAI.balanceOf(owner.address)).div(parseUnits("1", 18)).toString()) - .toString(); - expect(amountDeducted).equal(amountToDeduct); - - percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); - total = new BigNumber((await vWBTC.badDebt()).toString()).dividedBy(parseUnits("1", "8").toString()); - amountToDeduct = new BigNumber(total).times(percentageToDeduct).dividedBy(100).toString(); - amountDeducted = new BigNumber(previousWBTCBalance.toString()) - .minus((await mockWBTC.balanceOf(owner.address)).toString()) - .div(parseUnits("1", 8).toString()) - .toString(); - expect(amountDeducted).equal(amountToDeduct); - }); + expect(await fakeRiskFund.getPoolsBaseAssetReserves(comptroller.address)).equal( + parseUnits(riskFundBalance, 18).toString(), + ); - it("Should not be able to start auction while on is ongoing", async function () { - await expect(shortfall.startAuction(poolAddress)).to.be.revertedWith("auction is on-going"); - }); + expect(await vDAI.badDebt()).equal(parseUnits("1000", 18)); + expect(await vWBTC.badDebt()).equal(parseUnits("1", 8)); + }); - it("Should not be able to place bid lower than highest bid", async function () { - const auction = await shortfall.auctions(poolAddress); - await expect(shortfall.placeBid(poolAddress, "1200", auction.startBlock)).to.be.revertedWith( - "your bid is not the highest", - ); - }); + it("Should not be able to start auction when bad debt is low", async function () { + vDAI.badDebt.returns(parseUnits("20", 18)); + vWBTC.badDebt.returns(parseUnits("0.01", 8)); - it("Transfer back previous balance after second bid", async function () { - const auction = await shortfall.auctions(poolAddress); - const previousOwnerDaiBalance = await mockDAI.balanceOf(owner.address); + await expect(shortfall.startAuction(poolAddress)).to.be.revertedWith("pool bad debt is too low"); + }); - const percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); - const totalVDai = new BigNumber((await vDAI.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); - const amountToDeductVDai = new BigNumber(totalVDai).times(percentageToDeduct).dividedBy(100).toString(); + it("can't restart when there is no ongoing auction", async function () { + await expect(shortfall.restartAuction(poolAddress)).to.be.revertedWith("no on-going auction"); + }); - const previousOwnerWBtcBalance = await mockWBTC.balanceOf(owner.address); - const totalVBtc = new BigNumber((await vWBTC.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); - const amountToDeductVBtc = new BigNumber(totalVBtc).times(percentageToDeduct).dividedBy(100).toString(); + it("Should not be able to close auction when there is no active auction", async function () { + await expect(shortfall.closeAuction(poolAddress)).to.be.revertedWith("no on-going auction"); + }); - await shortfall.connect(bidder2).placeBid(poolAddress, "1800", auction.startBlock); + it("Should not be able to placeBid when there is no active auction", async function () { + vDAI.badDebt.returns(parseUnits("20", 18)); + vWBTC.badDebt.returns(parseUnits("0.01", 8)); + const auction = await shortfall.auctions(poolAddress); - expect(await mockDAI.balanceOf(owner.address)).to.be.equal( - previousOwnerDaiBalance.add(convertToUnit(amountToDeductVDai, 18)), - ); - expect(await mockWBTC.balanceOf(owner.address)).to.be.equal( - previousOwnerWBtcBalance.add(convertToUnit(amountToDeductVBtc, 18)), - ); - }); + await expect(shortfall.placeBid(poolAddress, "1800", auction.startBlockOrTimestamp)).to.be.revertedWith( + "no on-going auction", + ); + }); - it("can't close ongoing auction", async function () { - await expect(shortfall.closeAuction(poolAddress)).to.be.revertedWith( - "waiting for next bidder. cannot close auction", - ); - }); + it("Start auction", async function () { + vDAI.badDebt.returns(parseUnits("10000", 18)); + await vDAI.setVariable("badDebt", parseUnits("10000", 18)); + vWBTC.badDebt.returns(parseUnits("2", 8)); + await vWBTC.setVariable("badDebt", parseUnits("2", 8)); + + await shortfall.startAuction(poolAddress); + const auction = await shortfall.auctions(poolAddress); + startBlockNumber = auction.startBlockOrTimestamp; + expect(auction.status).equal(1); + expect(auction.auctionType).equal(0); + expect(auction.seizedRiskFund).equal(parseUnits(riskFundBalance, 18)); + + const startBidBps = new BigNumber("10000000000").dividedBy("52000.68").dividedBy("11000").toFixed(2); + expect(auction.startBidBps.toString()).equal(new BigNumber(startBidBps).times(100).toString()); + }); - it("Close Auction", async function () { - const originalBalance = await mockDAI.balanceOf(bidder2.address); - await mine((await shortfall.nextBidderBlockLimit()).toNumber() + 2); + it("Should not be able to place bid lower max basis points", async function () { + const auction = await shortfall.auctions(poolAddress); + await expect(shortfall.placeBid(poolAddress, "10001", auction.startBlockOrTimestamp)).to.be.revertedWith( + "basis points cannot be more than 10000", + ); + }); - // simulate transferReserveForAuction - await mockDAI.transfer(shortfall.address, parseUnits(riskFundBalance, 18)); - fakeRiskFund.transferReserveForAuction.returns(parseUnits("10000", 18)); + it("Place bid", async function () { + const auction = await shortfall.auctions(poolAddress); - await expect(shortfall.closeAuction(poolAddress)) - .to.emit(shortfall, "AuctionClosed") - .withArgs( - comptroller.address, - startBlockNumber, - bidder2.address, - 1800, - parseUnits("10000", 18), - [vDAI.address, vWBTC.address], - [parseUnits("1800", 18), "36000000"], + await mockDAI.approve(shortfall.address, parseUnits("10000", 18)); + await mockWBTC.approve(shortfall.address, parseUnits("2", 8)); + + const previousDaiBalance = await mockDAI.balanceOf(owner.address); + const previousWBTCBalance = await mockWBTC.balanceOf(owner.address); + + await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlockOrTimestamp); + expect((await mockDAI.balanceOf(owner.address)).div(parseUnits("1", 18)).toNumber()).lt( + previousDaiBalance.div(parseUnits("1", 18)).toNumber(), + ); + expect((await mockWBTC.balanceOf(owner.address)).div(parseUnits("1", 8)).toNumber()).lt( + previousWBTCBalance.div(parseUnits("1", 8)).toNumber(), ); - const auction = await shortfall.auctions(poolAddress); - expect(auction.status).equal(2); + let percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); + let total = new BigNumber((await vDAI.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); + let amountToDeduct = new BigNumber(total).times(percentageToDeduct).dividedBy(100).toString(); + let amountDeducted = new BigNumber(previousDaiBalance.div(parseUnits("1", 18)).toString()) + .minus((await mockDAI.balanceOf(owner.address)).div(parseUnits("1", 18)).toString()) + .toString(); + expect(amountDeducted).equal(amountToDeduct); + + percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); + total = new BigNumber((await vWBTC.badDebt()).toString()).dividedBy(parseUnits("1", "8").toString()); + amountToDeduct = new BigNumber(total).times(percentageToDeduct).dividedBy(100).toString(); + amountDeducted = new BigNumber(previousWBTCBalance.toString()) + .minus((await mockWBTC.balanceOf(owner.address)).toString()) + .div(parseUnits("1", 8).toString()) + .toString(); + expect(amountDeducted).equal(amountToDeduct); + }); - expect(vWBTC.badDebtRecovered).to.have.been.calledOnce; - expect(vWBTC.badDebtRecovered).to.have.been.calledWith("36000000"); + it("Should not be able to start auction while on is ongoing", async function () { + await expect(shortfall.startAuction(poolAddress)).to.be.revertedWith("auction is on-going"); + }); - expect(vDAI.badDebtRecovered).to.have.been.calledOnce; - expect(vDAI.badDebtRecovered).to.have.been.calledWith(parseUnits("1800", 18)); - expect(await mockDAI.balanceOf(bidder2.address)).to.be.equal(originalBalance.add(auction.seizedRiskFund)); - }); - }); + it("Should not be able to place bid lower than highest bid", async function () { + const auction = await shortfall.auctions(poolAddress); + await expect(shortfall.placeBid(poolAddress, "1200", auction.startBlockOrTimestamp)).to.be.revertedWith( + "your bid is not the highest", + ); + }); - describe("LARGE_RISK_FUND Scenario", async function () { - before(setup); - let startBlockNumber; - it("Start auction", async function () { - vDAI.badDebt.returns(parseUnits("10000", 18)); - await vDAI.setVariable("badDebt", parseUnits("10000", 18)); - vWBTC.badDebt.returns(parseUnits("1", 8)); - await vWBTC.setVariable("badDebt", parseUnits("1", 8)); + it("Transfer back previous balance after second bid", async function () { + const auction = await shortfall.auctions(poolAddress); + const previousOwnerDaiBalance = await mockDAI.balanceOf(owner.address); - riskFundBalance = "50000"; - fakeRiskFund.getPoolsBaseAssetReserves.returns(parseUnits(riskFundBalance, 18)); + const percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); + const totalVDai = new BigNumber((await vDAI.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); + const amountToDeductVDai = new BigNumber(totalVDai).times(percentageToDeduct).dividedBy(100).toString(); - const receipt = await shortfall.startAuction(poolAddress); - startBlockNumber = receipt.blockNumber; + const previousOwnerWBtcBalance = await mockWBTC.balanceOf(owner.address); + const totalVBtc = new BigNumber((await vWBTC.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); + const amountToDeductVBtc = new BigNumber(totalVBtc).times(percentageToDeduct).dividedBy(100).toString(); - const auction = await shortfall.auctions(poolAddress); - expect(auction.status).equal(1); - expect(auction.auctionType).equal(1); + await shortfall.connect(bidder2).placeBid(poolAddress, "1800", auction.startBlockOrTimestamp); - const startBidBps = new BigNumber(new BigNumber("21000.34").plus(10000).times(1.1).times(100)).dividedBy( - riskFundBalance, - ); - expect(new BigNumber(startBidBps).times(riskFundBalance).dividedBy(100).toString()).equal( - new BigNumber(auction.seizedRiskFund.toString()).dividedBy(parseUnits("1", 18).toString()).toString(), - ); - }); + expect(await mockDAI.balanceOf(owner.address)).to.be.equal( + previousOwnerDaiBalance.add(convertToUnit(amountToDeductVDai, 18)), + ); + expect(await mockWBTC.balanceOf(owner.address)).to.be.equal( + previousOwnerWBtcBalance.add(convertToUnit(amountToDeductVBtc, 18)), + ); + }); - it("Place bid", async function () { - const auction = await shortfall.auctions(poolAddress); + it("can't close ongoing auction", async function () { + await expect(shortfall.closeAuction(poolAddress)).to.be.revertedWith( + "waiting for next bidder. cannot close auction", + ); + }); - await mockDAI.approve(shortfall.address, parseUnits("10000", 18)); - await mockWBTC.approve(shortfall.address, parseUnits("1", 8)); - - const previousDaiBalance = await mockDAI.balanceOf(owner.address); - const previousWBTCBalance = await mockWBTC.balanceOf(owner.address); - - await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlock); - expect((await mockDAI.balanceOf(owner.address)).div(parseUnits("1", 18)).toNumber()).lt( - previousDaiBalance.div(parseUnits("1", 18)).toNumber(), - ); - expect((await mockWBTC.balanceOf(owner.address)).div(parseUnits("1", 8)).toNumber()).lt( - previousWBTCBalance.div(parseUnits("1", 8)).toNumber(), - ); - - let percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); - let total = new BigNumber((await vDAI.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); - let amountToDeduct = new BigNumber(total).times(percentageToDeduct).dividedBy(100).toString(); - let amountDeducted = new BigNumber(previousDaiBalance.div(parseUnits("1", 18)).toString()) - .minus((await mockDAI.balanceOf(owner.address)).div(parseUnits("1", 18)).toString()) - .toString(); - expect(amountDeducted).equal(amountToDeduct); - - percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); - total = new BigNumber((await vWBTC.badDebt()).toString()).dividedBy(parseUnits("1", "8").toString()); - amountToDeduct = new BigNumber(total).times(percentageToDeduct).dividedBy(100).toString(); - amountDeducted = new BigNumber(previousWBTCBalance.toString()) - .minus((await mockWBTC.balanceOf(owner.address)).toString()) - .div(parseUnits("1", 8).toString()) - .toString(); - expect(amountDeducted).equal(amountToDeduct); + it("Close Auction", async function () { + const originalBalance = await mockDAI.balanceOf(bidder2.address); + await mine((await shortfall.nextBidderBlockLimit()).toNumber() + 2); + + // simulate transferReserveForAuction + await mockDAI.transfer(shortfall.address, parseUnits(riskFundBalance, 18)); + fakeRiskFund.transferReserveForAuction.returns(parseUnits("10000", 18)); + + await expect(shortfall.closeAuction(poolAddress)) + .to.emit(shortfall, "AuctionClosed") + .withArgs( + comptroller.address, + startBlockNumber, + bidder2.address, + 1800, + parseUnits("10000", 18), + [vDAI.address, vWBTC.address], + [parseUnits("1800", 18), "36000000"], + ); + + const auction = await shortfall.auctions(poolAddress); + expect(auction.status).equal(2); + + expect(vWBTC.badDebtRecovered).to.have.been.calledOnce; + expect(vWBTC.badDebtRecovered).to.have.been.calledWith("36000000"); + + expect(vDAI.badDebtRecovered).to.have.been.calledOnce; + expect(vDAI.badDebtRecovered).to.have.been.calledWith(parseUnits("1800", 18)); + expect(await mockDAI.balanceOf(bidder2.address)).to.be.equal(originalBalance.add(auction.seizedRiskFund)); + }); }); - it("Transfer back previous balance after second bid", async function () { - const auction = await shortfall.auctions(poolAddress); - const previousOwnerDaiBalance = await mockDAI.balanceOf(owner.address); + describe("LARGE_RISK_FUND Scenario", async function () { + before(async function () { + await setup(isTimeBased); + }); + let startBlockNumber; + it("Start auction", async function () { + vDAI.badDebt.returns(parseUnits("10000", 18)); + await vDAI.setVariable("badDebt", parseUnits("10000", 18)); + vWBTC.badDebt.returns(parseUnits("1", 8)); + await vWBTC.setVariable("badDebt", parseUnits("1", 8)); - const percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); - const totalVDai = new BigNumber((await vDAI.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); - const amountToDeductVDai = new BigNumber(totalVDai).times(percentageToDeduct).dividedBy(100).toString(); + const newRiskFundBalance = "50000"; + fakeRiskFund.getPoolsBaseAssetReserves.returns(parseUnits(newRiskFundBalance, 18)); - const previousOwnerWBtcBalance = await mockWBTC.balanceOf(owner.address); - const totalVBtc = new BigNumber((await vWBTC.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); - const amountToDeductVBtc = new BigNumber(totalVBtc).times(percentageToDeduct).dividedBy(100).toString(); + await shortfall.startAuction(poolAddress); + startBlockNumber = (await shortfall.auctions(poolAddress)).startBlockOrTimestamp; - await shortfall.connect(bidder2).placeBid(poolAddress, "1800", auction.startBlock); + const auction = await shortfall.auctions(poolAddress); + expect(auction.status).equal(1); + expect(auction.auctionType).equal(1); - expect(await mockDAI.balanceOf(owner.address)).to.be.equal( - previousOwnerDaiBalance.add(convertToUnit(amountToDeductVDai, 18)), - ); - expect(await mockWBTC.balanceOf(owner.address)).to.be.equal( - previousOwnerWBtcBalance.add(convertToUnit(amountToDeductVBtc, 18)), - ); - }); + const startBidBps = new BigNumber(new BigNumber("21000.34").plus(10000).times(1.1).times(100)).dividedBy( + newRiskFundBalance, + ); + expect(new BigNumber(startBidBps).times(newRiskFundBalance).dividedBy(100).toString()).equal( + new BigNumber(auction.seizedRiskFund.toString()).dividedBy(parseUnits("1", 18).toString()).toString(), + ); + }); - it("Close Auction", async function () { - const originalBalance = await mockDAI.balanceOf(bidder2.address); - let auction = await shortfall.auctions(poolAddress); + it("Place bid", async function () { + const auction = await shortfall.auctions(poolAddress); - await mine((await shortfall.nextBidderBlockLimit()).toNumber() + 2); + await mockDAI.approve(shortfall.address, parseUnits("10000", 18)); + await mockWBTC.approve(shortfall.address, parseUnits("1", 8)); - // simulate transferReserveForAuction - await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); - fakeRiskFund.transferReserveForAuction.returns("6138067320000000000000"); + const previousDaiBalance = await mockDAI.balanceOf(owner.address); + const previousWBTCBalance = await mockWBTC.balanceOf(owner.address); - await expect(shortfall.closeAuction(poolAddress)) - .to.emit(shortfall, "AuctionClosed") - .withArgs( - comptroller.address, - startBlockNumber, - bidder2.address, - 1800, - "6138067320000000000000", - [vDAI.address, vWBTC.address], - [parseUnits("10000", 18), "100000000"], + await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlockOrTimestamp); + expect((await mockDAI.balanceOf(owner.address)).div(parseUnits("1", 18)).toNumber()).lt( + previousDaiBalance.div(parseUnits("1", 18)).toNumber(), + ); + expect((await mockWBTC.balanceOf(owner.address)).div(parseUnits("1", 8)).toNumber()).lt( + previousWBTCBalance.div(parseUnits("1", 8)).toNumber(), ); - auction = await shortfall.auctions(poolAddress); - expect(auction.status).equal(2); - expect(vWBTC.badDebtRecovered).to.have.been.calledTwice; - expect(vWBTC.badDebtRecovered).to.have.been.calledWith(parseUnits("1", 8)); + let percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); + let total = new BigNumber((await vDAI.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); + let amountToDeduct = new BigNumber(total).times(percentageToDeduct).dividedBy(100).toString(); + let amountDeducted = new BigNumber(previousDaiBalance.div(parseUnits("1", 18)).toString()) + .minus((await mockDAI.balanceOf(owner.address)).div(parseUnits("1", 18)).toString()) + .toString(); + expect(amountDeducted).equal(amountToDeduct); + + percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); + total = new BigNumber((await vWBTC.badDebt()).toString()).dividedBy(parseUnits("1", "8").toString()); + amountToDeduct = new BigNumber(total).times(percentageToDeduct).dividedBy(100).toString(); + amountDeducted = new BigNumber(previousWBTCBalance.toString()) + .minus((await mockWBTC.balanceOf(owner.address)).toString()) + .div(parseUnits("1", 8).toString()) + .toString(); + expect(amountDeducted).equal(amountToDeduct); + }); - expect(vDAI.badDebtRecovered).to.have.been.calledTwice; - expect(vDAI.badDebtRecovered).to.have.been.calledWith(parseUnits("10000", 18)); - const riskFundBidAmount = auction.seizedRiskFund.mul(auction.highestBidBps).div(10000); - expect(await mockDAI.balanceOf(bidder2.address)).to.be.equal(originalBalance.add(riskFundBidAmount)); - }); - }); + it("Transfer back previous balance after second bid", async function () { + const auction = await shortfall.auctions(poolAddress); + const previousOwnerDaiBalance = await mockDAI.balanceOf(owner.address); - describe("Restart Auction", async function () { - beforeEach(setup); + const percentageToDeduct = new BigNumber(auction.startBidBps.toString()).dividedBy(100); + const totalVDai = new BigNumber((await vDAI.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); + const amountToDeductVDai = new BigNumber(totalVDai).times(percentageToDeduct).dividedBy(100).toString(); - it("Can't restart auction early ", async function () { - vDAI.badDebt.returns(parseUnits("10000", 18)); - await vDAI.setVariable("badDebt", parseUnits("10000", 18)); - vWBTC.badDebt.returns(parseUnits("2", 8)); - await vWBTC.setVariable("badDebt", parseUnits("2", 8)); + const previousOwnerWBtcBalance = await mockWBTC.balanceOf(owner.address); + const totalVBtc = new BigNumber((await vWBTC.badDebt()).toString()).dividedBy(parseUnits("1", "18").toString()); + const amountToDeductVBtc = new BigNumber(totalVBtc).times(percentageToDeduct).dividedBy(100).toString(); - await shortfall.startAuction(poolAddress); - await mine(5); - await expect(shortfall.restartAuction(poolAddress)).to.be.revertedWith( - "you need to wait for more time for first bidder", - ); - }); + await shortfall.connect(bidder2).placeBid(poolAddress, "1800", auction.startBlockOrTimestamp); - it("Can restart auction", async function () { - vDAI.badDebt.returns(parseUnits("1000", 18)); - await vDAI.setVariable("badDebt", parseUnits("1000", 18)); - vWBTC.badDebt.returns(parseUnits("1", 8)); - await vWBTC.setVariable("badDebt", parseUnits("1", 8)); + expect(await mockDAI.balanceOf(owner.address)).to.be.equal( + previousOwnerDaiBalance.add(convertToUnit(amountToDeductVDai, 18)), + ); + expect(await mockWBTC.balanceOf(owner.address)).to.be.equal( + previousOwnerWBtcBalance.add(convertToUnit(amountToDeductVBtc, 18)), + ); + }); - const receipt = await shortfall.startAuction(poolAddress); + it("Close Auction", async function () { + const originalBalance = await mockDAI.balanceOf(bidder2.address); + let auction = await shortfall.auctions(poolAddress); + + await mine((await shortfall.nextBidderBlockLimit()).toNumber() + 2); + + // simulate transferReserveForAuction + await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); + fakeRiskFund.transferReserveForAuction.returns("6138067320000000000000"); + + await expect(shortfall.closeAuction(poolAddress)) + .to.emit(shortfall, "AuctionClosed") + .withArgs( + comptroller.address, + startBlockNumber, + bidder2.address, + 1800, + "6138067320000000000000", + [vDAI.address, vWBTC.address], + [parseUnits("10000", 18), "100000000"], + ); + auction = await shortfall.auctions(poolAddress); + expect(auction.status).equal(2); + + expect(vWBTC.badDebtRecovered).to.have.been.calledTwice; + expect(vWBTC.badDebtRecovered).to.have.been.calledWith(parseUnits("1", 8)); + + expect(vDAI.badDebtRecovered).to.have.been.calledTwice; + expect(vDAI.badDebtRecovered).to.have.been.calledWith(parseUnits("10000", 18)); + const riskFundBidAmount = auction.seizedRiskFund.mul(auction.highestBidBps).div(10000); + expect(await mockDAI.balanceOf(bidder2.address)).to.be.equal(originalBalance.add(riskFundBidAmount)); + }); + }); - await mine(100); + describe("Restart Auction", async function () { + beforeEach(async function () { + await setup(isTimeBased); + }); - await expect(shortfall.restartAuction(poolAddress)) - .to.emit(shortfall, "AuctionRestarted") - .withArgs(poolAddress, receipt.blockNumber); - }); + it("Can't restart auction early ", async function () { + vDAI.badDebt.returns(parseUnits("10000", 18)); + await vDAI.setVariable("badDebt", parseUnits("10000", 18)); + vWBTC.badDebt.returns(parseUnits("2", 8)); + await vWBTC.setVariable("badDebt", parseUnits("2", 8)); - it("Cannot restart auction after a bid is placed", async function () { - vDAI.badDebt.returns(parseUnits("1000", 18)); - await vDAI.setVariable("badDebt", parseUnits("1000", 18)); - vWBTC.badDebt.returns(parseUnits("1", 8)); - await vWBTC.setVariable("badDebt", parseUnits("1", 8)); + await shortfall.startAuction(poolAddress); + await mine(5); + await expect(shortfall.restartAuction(poolAddress)).to.be.revertedWith( + "you need to wait for more time for first bidder", + ); + }); - await shortfall.startAuction(poolAddress); - const auction = await shortfall.auctions(poolAddress); + it("Can restart auction", async function () { + vDAI.badDebt.returns(parseUnits("1000", 18)); + await vDAI.setVariable("badDebt", parseUnits("1000", 18)); + vWBTC.badDebt.returns(parseUnits("1", 8)); + await vWBTC.setVariable("badDebt", parseUnits("1", 8)); - await mockDAI.approve(shortfall.address, parseUnits("50000", 18)); - await mockWBTC.approve(shortfall.address, parseUnits("50000", 8)); + await shortfall.startAuction(poolAddress); + const startBlockNumberOrTimestamp = (await shortfall.auctions(poolAddress)).startBlockOrTimestamp; - // simulate transferReserveForAuction - await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); + if (!isTimeBased) { + await mine(100); + } else { + await mine(300); + } - await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlock); + await expect(shortfall.restartAuction(poolAddress)) + .to.emit(shortfall, "AuctionRestarted") + .withArgs(poolAddress, startBlockNumberOrTimestamp); + }); - await mine(100); + it("Cannot restart auction after a bid is placed", async function () { + vDAI.badDebt.returns(parseUnits("1000", 18)); + await vDAI.setVariable("badDebt", parseUnits("1000", 18)); + vWBTC.badDebt.returns(parseUnits("1", 8)); + await vWBTC.setVariable("badDebt", parseUnits("1", 8)); - await expect(shortfall.restartAuction(poolAddress)).to.be.revertedWith( - "you need to wait for more time for first bidder", - ); - // Close out auction created for this test case - await mine(10); - await shortfall.closeAuction(poolAddress); - }); + await shortfall.startAuction(poolAddress); + const auction = await shortfall.auctions(poolAddress); - it("Cannot restart auction if auctions paused", async function () { - vDAI.badDebt.returns(parseUnits("1000", 18)); - await vDAI.setVariable("badDebt", parseUnits("1000", 18)); - vWBTC.badDebt.returns(parseUnits("1", 8)); - await vWBTC.setVariable("badDebt", parseUnits("1", 8)); + await mockDAI.approve(shortfall.address, parseUnits("50000", 18)); + await mockWBTC.approve(shortfall.address, parseUnits("50000", 8)); - await shortfall.startAuction(poolAddress); - const auction = await shortfall.auctions(poolAddress); + // simulate transferReserveForAuction + await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); - await mockDAI.approve(shortfall.address, parseUnits("50000", 18)); - await mockWBTC.approve(shortfall.address, parseUnits("50000", 8)); + await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlockOrTimestamp); - // simulate transferReserveForAuction - await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); + if (!isTimeBased) { + await mine(100); + } else { + await mine(300); + } - await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlock); + await expect(shortfall.restartAuction(poolAddress)).to.be.revertedWith( + "you need to wait for more time for first bidder", + ); + // Close out auction created for this test case + await mine(10); + await shortfall.closeAuction(poolAddress); + }); - await mine(100); - await shortfall.pauseAuctions(); - await expect(shortfall.restartAuction(poolAddress)).to.be.revertedWith("auctions are paused"); - // Close out auction created for this test case - await mine(10); - await shortfall.closeAuction(poolAddress); - await shortfall.resumeAuctions(); + it("Cannot restart auction if auctions paused", async function () { + vDAI.badDebt.returns(parseUnits("1000", 18)); + await vDAI.setVariable("badDebt", parseUnits("1000", 18)); + vWBTC.badDebt.returns(parseUnits("1", 8)); + await vWBTC.setVariable("badDebt", parseUnits("1", 8)); + + await shortfall.startAuction(poolAddress); + const auction = await shortfall.auctions(poolAddress); + + await mockDAI.approve(shortfall.address, parseUnits("50000", 18)); + await mockWBTC.approve(shortfall.address, parseUnits("50000", 8)); + + // simulate transferReserveForAuction + await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); + + await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlockOrTimestamp); + + if (!isTimeBased) { + await mine(100); + } else { + await mine(300); + } + await shortfall.pauseAuctions(); + await expect(shortfall.restartAuction(poolAddress)).to.be.revertedWith("auctions are paused"); + // Close out auction created for this test case + await mine(10); + await shortfall.closeAuction(poolAddress); + await shortfall.resumeAuctions(); + }); }); - }); - describe("Auctions can be enabled and disabled", async function () { - it("fails if called by a non permissioned account", async function () { - await expect(shortfall.connect(someone).pauseAuctions()).to.be.reverted; - }); + describe("Auctions can be enabled and disabled", async function () { + it("fails if called by a non permissioned account", async function () { + await expect(shortfall.connect(someone).pauseAuctions()).to.be.reverted; + }); - it("can close current auction but not start new one when they are paused", async function () { - vDAI.badDebt.returns(parseUnits("10000", 18)); - await vDAI.setVariable("badDebt", parseUnits("10000", 18)); - vWBTC.badDebt.returns(parseUnits("2", 8)); - await vWBTC.setVariable("badDebt", parseUnits("2", 8)); + it("can close current auction but not start new one when they are paused", async function () { + vDAI.badDebt.returns(parseUnits("10000", 18)); + await vDAI.setVariable("badDebt", parseUnits("10000", 18)); + vWBTC.badDebt.returns(parseUnits("2", 8)); + await vWBTC.setVariable("badDebt", parseUnits("2", 8)); - await shortfall.startAuction(poolAddress); - const auction = await shortfall.auctions(poolAddress); + await shortfall.startAuction(poolAddress); + const auction = await shortfall.auctions(poolAddress); - // simulate transferReserveForAuction - await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); + // simulate transferReserveForAuction + await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); - await expect(shortfall.connect(owner).pauseAuctions()) - .to.emit(shortfall, "AuctionsPaused") - .withArgs(owner.address); + await expect(shortfall.connect(owner).pauseAuctions()) + .to.emit(shortfall, "AuctionsPaused") + .withArgs(owner.address); - await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlock); - // Close out auction created for this test case - await mine(10); - await expect(shortfall.closeAuction(poolAddress)); - await expect(shortfall.startAuction(poolAddress)).to.be.revertedWith("Auctions are paused"); + await shortfall.placeBid(poolAddress, auction.startBidBps, auction.startBlockOrTimestamp); + // Close out auction created for this test case + await mine(10); + await expect(shortfall.closeAuction(poolAddress)); + await expect(shortfall.startAuction(poolAddress)).to.be.revertedWith("Auctions are paused"); + }); }); }); -}); -describe("Shortfall: Deflationary token Scenario", async function () { - before(async () => { - await mine(1000); - await setup(); - }); - let startBlockNumber; - it("Start auction", async function () { - vDAI.badDebt.returns("0"); - vWBTC.badDebt.returns("0"); - vFloki.badDebt.returns(parseUnits("100", 18)); - await vFloki.setVariable("badDebt", parseUnits("100", 18)); + describe(`${description}Shortfall: Deflationary token Scenario`, async function () { + let startBlockNumberOrTimestamp; - riskFundBalance = "500"; - fakeRiskFund.getPoolsBaseAssetReserves.returns(parseUnits(riskFundBalance, 18)); + before(async () => { + await mine(1000); + await setup(isTimeBased); + }); - await shortfall.connect(owner).updateMinimumPoolBadDebt(convertToUnit(10, 18)); + it("Start auction", async function () { + vDAI.badDebt.returns("0"); + vWBTC.badDebt.returns("0"); + vFloki.badDebt.returns(parseUnits("100", 18)); + await vFloki.setVariable("badDebt", parseUnits("100", 18)); - const receipt = await shortfall.startAuction(poolAddress); - startBlockNumber = receipt.blockNumber; + const newRiskFundBalance = "500"; + fakeRiskFund.getPoolsBaseAssetReserves.returns(parseUnits(newRiskFundBalance, 18)); - const auction = await shortfall.auctions(poolAddress); - expect(auction.status).equal(1); - expect(auction.auctionType).equal(1); - }); + await shortfall.connect(owner).updateMinimumPoolBadDebt(convertToUnit(10, 18)); - it("Place bid", async function () { - const auction = await shortfall.auctions(poolAddress); - await mockFloki.approve(shortfall.address, parseUnits("100", 18)); + await shortfall.startAuction(poolAddress); + startBlockNumberOrTimestamp = (await shortfall.auctions(poolAddress)).startBlockOrTimestamp; - const tx = await shortfall.connect(bidder1).placeBid(poolAddress, auction.startBidBps, auction.startBlock); + const auction = await shortfall.auctions(poolAddress); + expect(auction.status).equal(1); + expect(auction.auctionType).equal(1); + }); - await expect(tx).to.changeTokenBalance(mockFloki, bidder1.address, "-100000000000000000000"); - await expect(tx).to.changeTokenBalance(mockFloki, shortfall.address, convertToUnit("99", 18)); - }); + it("Place bid", async function () { + const auction = await shortfall.auctions(poolAddress); + await mockFloki.approve(shortfall.address, parseUnits("100", 18)); - it("Transfer back previous balance after second bid", async function () { - const auction = await shortfall.auctions(poolAddress); - const tx = await shortfall.connect(bidder2).placeBid(poolAddress, "120", auction.startBlock); + const tx = await shortfall + .connect(bidder1) + .placeBid(poolAddress, auction.startBidBps, auction.startBlockOrTimestamp); - await expect(tx).to.changeTokenBalance(mockFloki, bidder1.address, "98010000000000000000"); - await expect(tx).to.changeTokenBalance(mockFloki, bidder2.address, "-100000000000000000000"); - await expect(tx).to.changeTokenBalance(mockFloki, shortfall.address, "0"); - }); + await expect(tx).to.changeTokenBalance(mockFloki, bidder1.address, "-100000000000000000000"); + await expect(tx).to.changeTokenBalance(mockFloki, shortfall.address, convertToUnit("99", 18)); + }); + + it("Transfer back previous balance after second bid", async function () { + const auction = await shortfall.auctions(poolAddress); + const tx = await shortfall.connect(bidder2).placeBid(poolAddress, "120", auction.startBlockOrTimestamp); + + await expect(tx).to.changeTokenBalance(mockFloki, bidder1.address, "98010000000000000000"); + await expect(tx).to.changeTokenBalance(mockFloki, bidder2.address, "-100000000000000000000"); + await expect(tx).to.changeTokenBalance(mockFloki, shortfall.address, "0"); + }); - it("Close Auction", async function () { - const originalBalance = await mockDAI.balanceOf(bidder2.address); - let auction = await shortfall.auctions(poolAddress); + it("Close Auction", async function () { + const originalBalance = await mockDAI.balanceOf(bidder2.address); + let auction = await shortfall.auctions(poolAddress); - await mine((await shortfall.nextBidderBlockLimit()).toNumber() + 2); + await mine((await shortfall.nextBidderBlockLimit()).toNumber() + 2); - // simulate transferReserveForAuction - await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); + // simulate transferReserveForAuction + await mockDAI.transfer(shortfall.address, auction.seizedRiskFund); - const tx = await shortfall.closeAuction(poolAddress); - await expect(tx) - .to.emit(shortfall, "AuctionClosed") - .withArgs( - comptroller.address, - startBlockNumber, - bidder2.address, - 120, - "6138067320000000000000", - [vDAI.address, vWBTC.address, vFloki.address], - ["0", "0", "98010000000000000000"], - ); + const tx = await shortfall.closeAuction(poolAddress); + await expect(tx) + .to.emit(shortfall, "AuctionClosed") + .withArgs( + comptroller.address, + startBlockNumberOrTimestamp, + bidder2.address, + 120, + "6138067320000000000000", + [vDAI.address, vWBTC.address, vFloki.address], + ["0", "0", "98010000000000000000"], + ); - await expect(tx).to.changeTokenBalance(mockFloki, vFloki.address, "98010000000000000000"); + await expect(tx).to.changeTokenBalance(mockFloki, vFloki.address, "98010000000000000000"); - auction = await shortfall.auctions(poolAddress); - expect(auction.status).equal(2); + auction = await shortfall.auctions(poolAddress); + expect(auction.status).equal(2); - expect(vFloki.badDebtRecovered).to.have.been.calledWith("98010000000000000000"); + expect(vFloki.badDebtRecovered).to.have.been.calledWith("98010000000000000000"); - const riskFundBidAmount = auction.seizedRiskFund.mul(auction.highestBidBps).div(10000); + const riskFundBidAmount = auction.seizedRiskFund.mul(auction.highestBidBps).div(10000); - expect(await mockDAI.balanceOf(bidder2.address)).to.be.equal(originalBalance.add(riskFundBidAmount)); + expect(await mockDAI.balanceOf(bidder2.address)).to.be.equal(originalBalance.add(riskFundBidAmount)); + }); }); -}); +} diff --git a/tests/hardhat/Tokens/accrueInterestTest.ts b/tests/hardhat/Tokens/accrueInterestTest.ts index 5a146b336..bfeee0108 100644 --- a/tests/hardhat/Tokens/accrueInterestTest.ts +++ b/tests/hardhat/Tokens/accrueInterestTest.ts @@ -7,15 +7,17 @@ import { parseUnits } from "ethers/lib/utils"; import { InterestRateModel, VTokenHarness } from "../../../typechain"; import { vTokenTestFixture } from "../util/TokenTestHelpers"; +import { getDescription } from "../util/descriptionHelpers"; const { expect } = chai; chai.use(smock.matchers); const blockNumber = 2e7; +const blockTimestamp = 1700033367; const borrowIndex = parseUnits("1", 18).toBigInt(); const borrowRate = parseUnits("0.000001", 18).toBigInt(); -async function pretendBlock( +async function pretendBlockOrTimestamp( vToken: VTokenHarness, accrualBlock: BigNumberish = blockNumber, deltaBlocks: BigNumberish = 1, @@ -38,110 +40,121 @@ async function preAccrue({ await vToken.harnessExchangeRateDetails(0, 0, 0); } -describe("VToken", () => { - let vToken: VTokenHarness; - let interestRateModel: FakeContract; - - beforeEach(async () => { - const contracts = await loadFixture(vTokenTestFixture); - ({ vToken, interestRateModel } = contracts); - await vToken.setReduceReservesBlockDelta(parseUnits("4", 10)); - }); - - beforeEach(async () => { - await preAccrue({ vToken, interestRateModel }); - }); - - describe("accrueInterest", () => { - it("reverts if the interest rate is absurdly high", async () => { - await pretendBlock(vToken, blockNumber, 1); - expect(await vToken.getBorrowRateMaxMantissa()).to.equal(parseUnits("0.000005", 18)); // 0.0005% per block - interestRateModel.getBorrowRate.returns(parseUnits("0.00001", 18)); // 0.0010% per block - await expect(vToken.accrueInterest()).to.be.revertedWith("borrow rate is absurdly high"); - }); - - it("fails if new borrow rate calculation fails", async () => { - await pretendBlock(vToken, blockNumber, 1); - interestRateModel.getBorrowRate.reverts("Oups"); - await expect(vToken.accrueInterest()).to.be.reverted; // With("INTEREST_RATE_MODEL_ERROR"); - }); - - it("fails if simple interest factor calculation fails", async () => { - await pretendBlock(vToken, blockNumber, parseUnits("5", 70)); - await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); - }); - - it("fails if new borrow index calculation fails", async () => { - await pretendBlock(vToken, blockNumber, parseUnits("5", 60)); - await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); - }); - - it("fails if new borrow interest index calculation fails", async () => { - await pretendBlock(vToken); - await vToken.harnessSetBorrowIndex(constants.MaxUint256); - await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); - }); +function getBlockNumberOrTimestamp(isTimeBased: boolean) { + if (!isTimeBased) { + return blockNumber; + } + return blockTimestamp; +} - it("fails if interest accumulated calculation fails", async () => { - await vToken.harnessExchangeRateDetails(0, constants.MaxUint256, 0); - await pretendBlock(vToken); - await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); - }); +for (const isTimeBased of [false, true]) { + const description = getDescription(isTimeBased); - it("fails if new total borrows calculation fails", async () => { - interestRateModel.getBorrowRate.returns("1"); - await pretendBlock(vToken); - await vToken.harnessExchangeRateDetails(0, constants.MaxUint256, 0); - await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); - }); + describe(`${description}VToken`, () => { + let vToken: VTokenHarness; + let interestRateModel: FakeContract; - it("fails if interest accumulated for reserves calculation fails", async () => { - interestRateModel.getBorrowRate.returns(parseUnits("0.000001", 18)); - await vToken.harnessExchangeRateDetails(0, parseUnits("1", 30), constants.MaxUint256); - await vToken.harnessSetReserveFactorFresh(parseUnits("1", 10)); - await pretendBlock(vToken, blockNumber, parseUnits("5", 20)); - await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); + beforeEach(async () => { + const contracts = await loadFixture(vTokenTestFixture); + ({ vToken, interestRateModel } = contracts); + await vToken.setReduceReservesBlockDelta(parseUnits("4", 10)); }); - it("fails if new total reserves calculation fails", async () => { - interestRateModel.getBorrowRate.returns("1"); - await vToken.harnessExchangeRateDetails(0, parseUnits("1", 56), constants.MaxUint256); - await vToken.harnessSetReserveFactorFresh(parseUnits("1", 17)); - await pretendBlock(vToken); - await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); + beforeEach(async () => { + await preAccrue({ vToken, interestRateModel }); }); - it("succeeds and saves updated values in storage on success", async () => { - const startingTotalBorrows = parseUnits("1", 22); - const startingTotalReserves = parseUnits("1", 20); - const reserveFactor = parseUnits("1", 17); - - await vToken.harnessExchangeRateDetails(0, startingTotalBorrows, startingTotalReserves); - await vToken.harnessSetReserveFactorFresh(reserveFactor); - await pretendBlock(vToken); - - const expectedAccrualBlockNumber = blockNumber + 1; - const expectedBorrowIndex = BigNumber.from(borrowIndex).add( - BigNumber.from(borrowIndex).mul(borrowRate).div(parseUnits("1", 18)), - ); - const expectedTotalBorrows = startingTotalBorrows.add( - startingTotalBorrows.mul(borrowRate).div(parseUnits("1", 18)), - ); - const expectedTotalReserves = startingTotalReserves.add( - startingTotalBorrows.mul(borrowRate).mul(reserveFactor).div(parseUnits("1", 36)), - ); - - const receipt = await vToken.accrueInterest(); - const expectedInterestAccumulated = expectedTotalBorrows.sub(startingTotalBorrows); - - await expect(receipt) - .to.emit(vToken, "AccrueInterest") - .withArgs(0, expectedInterestAccumulated, expectedBorrowIndex, expectedTotalBorrows); - - expect(await vToken.accrualBlockNumber()).to.equal(expectedAccrualBlockNumber); - expect(await vToken.borrowIndex()).to.equal(expectedBorrowIndex); - expect(await vToken.totalBorrows()).to.equal(expectedTotalBorrows); - expect(await vToken.totalReserves()).to.equal(expectedTotalReserves); + describe("accrueInterest", () => { + it("reverts if the interest rate is absurdly high", async () => { + await pretendBlockOrTimestamp(vToken, getBlockNumberOrTimestamp(isTimeBased), 1); + expect(await vToken.getBorrowRateMaxMantissa()).to.equal(parseUnits("0.000005", 18)); // 0.0005% per block + interestRateModel.getBorrowRate.returns(parseUnits("0.00001", 18)); // 0.0010% per block + await expect(vToken.accrueInterest()).to.be.revertedWith("borrow rate is absurdly high"); + }); + + it("fails if new borrow rate calculation fails", async () => { + await pretendBlockOrTimestamp(vToken, getBlockNumberOrTimestamp(isTimeBased), 1); + interestRateModel.getBorrowRate.reverts("Oups"); + await expect(vToken.accrueInterest()).to.be.reverted; // With("INTEREST_RATE_MODEL_ERROR"); + }); + + it("fails if simple interest factor calculation fails", async () => { + await pretendBlockOrTimestamp(vToken, getBlockNumberOrTimestamp(isTimeBased), parseUnits("5", 70)); + await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); + }); + + it("fails if new borrow index calculation fails", async () => { + await pretendBlockOrTimestamp(vToken, getBlockNumberOrTimestamp(isTimeBased), parseUnits("5", 60)); + await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); + }); + + it("fails if new borrow interest index calculation fails", async () => { + await pretendBlockOrTimestamp(vToken, getBlockNumberOrTimestamp(isTimeBased), 1); + await vToken.harnessSetBorrowIndex(constants.MaxUint256); + await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); + }); + + it("fails if interest accumulated calculation fails", async () => { + await vToken.harnessExchangeRateDetails(0, constants.MaxUint256, 0); + await pretendBlockOrTimestamp(vToken, getBlockNumberOrTimestamp(isTimeBased), 1); + await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); + }); + + it("fails if new total borrows calculation fails", async () => { + interestRateModel.getBorrowRate.returns("1"); + await pretendBlockOrTimestamp(vToken, getBlockNumberOrTimestamp(isTimeBased), 1); + await vToken.harnessExchangeRateDetails(0, constants.MaxUint256, 0); + await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); + }); + + it("fails if interest accumulated for reserves calculation fails", async () => { + interestRateModel.getBorrowRate.returns(parseUnits("0.000001", 18)); + await vToken.harnessExchangeRateDetails(0, parseUnits("1", 30), constants.MaxUint256); + await vToken.harnessSetReserveFactorFresh(parseUnits("1", 10)); + await pretendBlockOrTimestamp(vToken, getBlockNumberOrTimestamp(isTimeBased), parseUnits("5", 20)); + await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); + }); + + it("fails if new total reserves calculation fails", async () => { + interestRateModel.getBorrowRate.returns("1"); + await vToken.harnessExchangeRateDetails(0, parseUnits("1", 56), constants.MaxUint256); + await vToken.harnessSetReserveFactorFresh(parseUnits("1", 17)); + await pretendBlockOrTimestamp(vToken); + await expect(vToken.accrueInterest()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW); + }); + + it("succeeds and saves updated values in storage on success", async () => { + const startingTotalBorrows = parseUnits("1", 22); + const startingTotalReserves = parseUnits("1", 20); + const reserveFactor = parseUnits("1", 17); + + await vToken.harnessExchangeRateDetails(0, startingTotalBorrows, startingTotalReserves); + await vToken.harnessSetReserveFactorFresh(reserveFactor); + await pretendBlockOrTimestamp(vToken, getBlockNumberOrTimestamp(isTimeBased), 1); + + const expectedAccrualBlockNumberOrTimestamp = getBlockNumberOrTimestamp(isTimeBased) + 1; + const expectedBorrowIndex = BigNumber.from(borrowIndex).add( + BigNumber.from(borrowIndex).mul(borrowRate).div(parseUnits("1", 18)), + ); + const expectedTotalBorrows = startingTotalBorrows.add( + startingTotalBorrows.mul(borrowRate).div(parseUnits("1", 18)), + ); + const expectedTotalReserves = startingTotalReserves.add( + startingTotalBorrows.mul(borrowRate).mul(reserveFactor).div(parseUnits("1", 36)), + ); + + const receipt = await vToken.accrueInterest(); + const expectedInterestAccumulated = expectedTotalBorrows.sub(startingTotalBorrows); + + await expect(receipt) + .to.emit(vToken, "AccrueInterest") + .withArgs(0, expectedInterestAccumulated, expectedBorrowIndex, expectedTotalBorrows); + + expect(await vToken.accrualBlockNumber()).to.equal(expectedAccrualBlockNumberOrTimestamp); + expect(await vToken.borrowIndex()).to.equal(expectedBorrowIndex); + expect(await vToken.totalBorrows()).to.equal(expectedTotalBorrows); + expect(await vToken.totalReserves()).to.equal(expectedTotalReserves); + }); }); }); -}); +} diff --git a/tests/hardhat/UpgradedVToken.ts b/tests/hardhat/UpgradedVToken.ts index 613f8c7d2..1d7171ce3 100644 --- a/tests/hardhat/UpgradedVToken.ts +++ b/tests/hardhat/UpgradedVToken.ts @@ -3,6 +3,7 @@ import { expect } from "chai"; import { parseUnits } from "ethers/lib/utils"; import { ethers, upgrades } from "hardhat"; +import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; import { convertToUnit } from "../../helpers/utils"; import { AccessControlManager, @@ -14,6 +15,7 @@ import { UpgradeableBeacon, } from "../../typechain"; import { deployVTokenBeacon, makeVToken } from "./util/TokenTestHelpers"; +import { getDescription } from "./util/descriptionHelpers"; // Disable a warning about mixing beacons and transparent proxies upgrades.silenceWarnings(); @@ -24,92 +26,107 @@ let comptroller1Proxy: Comptroller; let mockWBTC: MockToken; let fakeAccessControlManager: FakeContract; -describe("UpgradedVToken: Tests", function () { - /** - * Deploying required contracts along with the poolRegistry. - */ - before(async function () { - const [root] = await ethers.getSigners(); - - fakeAccessControlManager = await smock.fake("AccessControlManager"); - fakeAccessControlManager.isAllowedToCall.returns(true); - - const PoolRegistry = await ethers.getContractFactory("PoolRegistry"); - poolRegistry = (await upgrades.deployProxy(PoolRegistry, [fakeAccessControlManager.address])) as PoolRegistry; - - // Deploy Mock Tokens - const MockWBTC = await ethers.getContractFactory("MockToken"); - mockWBTC = await MockWBTC.deploy("Bitcoin", "BTC", 8); - - const _closeFactor = convertToUnit(0.05, 18); - const _liquidationIncentive = convertToUnit(1, 18); - const _minLiquidatableCollateral = convertToUnit(100, 18); - const maxLoopsLimit = 150; - - // Deploy Price Oracle - const MockPriceOracle = await ethers.getContractFactory("MockPriceOracle"); - const priceOracle = await MockPriceOracle.deploy(); - - const btcPrice = "21000.34"; - - await priceOracle.setPrice(mockWBTC.address, convertToUnit(btcPrice, 28)); - - const Comptroller = await ethers.getContractFactory("Comptroller"); - const comptrollerBeacon = await upgrades.deployBeacon(Comptroller, { constructorArgs: [poolRegistry.address] }); - - comptroller1Proxy = (await upgrades.deployBeaconProxy(comptrollerBeacon, Comptroller, [ - maxLoopsLimit, - fakeAccessControlManager.address, - ])) as Comptroller; - await comptroller1Proxy.setPriceOracle(priceOracle.address); - - // Registering the first pool - await poolRegistry.addPool( - "Pool 1", - comptroller1Proxy.address, - _closeFactor, - _liquidationIncentive, - _minLiquidatableCollateral, - ); - - vTokenBeacon = await deployVTokenBeacon(); - const vWBTC = await makeVToken({ - underlying: mockWBTC.address, - comptroller: comptroller1Proxy.address, - accessControlManager: fakeAccessControlManager.address, - admin: root.address, - beacon: vTokenBeacon, +for (const isTimeBased of [false, true]) { + const description = getDescription(isTimeBased); + const slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; + + describe(`${description}UpgradedVToken: Tests`, function () { + /** + * Deploying required contracts along with the poolRegistry. + */ + before(async function () { + const [root] = await ethers.getSigners(); + + fakeAccessControlManager = await smock.fake("AccessControlManager"); + fakeAccessControlManager.isAllowedToCall.returns(true); + + const PoolRegistry = await ethers.getContractFactory("PoolRegistry"); + poolRegistry = (await upgrades.deployProxy(PoolRegistry, [fakeAccessControlManager.address])) as PoolRegistry; + + // Deploy Mock Tokens + const MockWBTC = await ethers.getContractFactory("MockToken"); + mockWBTC = await MockWBTC.deploy("Bitcoin", "BTC", 8); + + const _closeFactor = convertToUnit(0.05, 18); + const _liquidationIncentive = convertToUnit(1, 18); + const _minLiquidatableCollateral = convertToUnit(100, 18); + const maxLoopsLimit = 150; + + // Deploy Price Oracle + const MockPriceOracle = await ethers.getContractFactory("MockPriceOracle"); + const priceOracle = await MockPriceOracle.deploy(); + + const btcPrice = "21000.34"; + + await priceOracle.setPrice(mockWBTC.address, convertToUnit(btcPrice, 28)); + + const Comptroller = await ethers.getContractFactory("Comptroller"); + const comptrollerBeacon = await upgrades.deployBeacon(Comptroller, { constructorArgs: [poolRegistry.address] }); + + comptroller1Proxy = (await upgrades.deployBeaconProxy(comptrollerBeacon, Comptroller, [ + maxLoopsLimit, + fakeAccessControlManager.address, + ])) as Comptroller; + await comptroller1Proxy.setPriceOracle(priceOracle.address); + + // Registering the first pool + await poolRegistry.addPool( + "Pool 1", + comptroller1Proxy.address, + _closeFactor, + _liquidationIncentive, + _minLiquidatableCollateral, + ); + + vTokenBeacon = await deployVTokenBeacon(); + const vWBTC = await makeVToken({ + underlying: mockWBTC.address, + comptroller: comptroller1Proxy.address, + accessControlManager: fakeAccessControlManager.address, + admin: root.address, + beacon: vTokenBeacon, + isTimeBased: isTimeBased, + blocksPerYear: slotsPerYear, + }); + + const initialSupply = parseUnits("1000", 18); + await mockWBTC.faucet(initialSupply); + await mockWBTC.approve(poolRegistry.address, initialSupply); + + // Deploy VTokens + await poolRegistry.addMarket({ + vToken: vWBTC.address, + collateralFactor: parseUnits("0.7", 18), + liquidationThreshold: parseUnits("0.7", 18), + initialSupply, + vTokenReceiver: root.address, + supplyCap: initialSupply, + borrowCap: initialSupply, + }); }); - const initialSupply = parseUnits("1000", 18); - await mockWBTC.faucet(initialSupply); - await mockWBTC.approve(poolRegistry.address, initialSupply); - - // Deploy VTokens - await poolRegistry.addMarket({ - vToken: vWBTC.address, - collateralFactor: parseUnits("0.7", 18), - liquidationThreshold: parseUnits("0.7", 18), - initialSupply, - vTokenReceiver: root.address, - supplyCap: initialSupply, - borrowCap: initialSupply, - }); - }); + it("Upgrade the vToken contract", async function () { + const vToken = await ethers.getContractFactory("UpgradedVToken"); + const vTokenDeploy = await vToken.deploy(isTimeBased, slotsPerYear); - it("Upgrade the vToken contract", async function () { - const vToken = await ethers.getContractFactory("UpgradedVToken"); - const vTokenDeploy = await vToken.deploy(); - await vTokenDeploy.deployed(); + await vTokenDeploy.deployed(); - await vTokenBeacon.upgradeTo(vTokenDeploy.address); - const upgradeTo = await vTokenBeacon.callStatic.implementation(); - expect(upgradeTo).to.be.equal(vTokenDeploy.address); + await vTokenBeacon.upgradeTo(vTokenDeploy.address); + const upgradeTo = await vTokenBeacon.callStatic.implementation(); + expect(upgradeTo).to.be.equal(vTokenDeploy.address); + const pools = await poolRegistry.callStatic.getAllPools(); + const vWBTCAddress = await poolRegistry.getVTokenForAsset(pools[0].comptroller, mockWBTC.address); + const vWBTC = await ethers.getContractAt("UpgradedVToken", vWBTCAddress); - const pools = await poolRegistry.callStatic.getAllPools(); - const vWBTCAddress = await poolRegistry.getVTokenForAsset(pools[0].comptroller, mockWBTC.address); - const vWBTC = await ethers.getContractAt("UpgradedVToken", vWBTCAddress); + if (!isTimeBased) { + const blockNumber = (await ethers.provider.getBlock("latest")).number; + expect(await vWBTC.getBlockNumberOrTimestamp()).to.closeTo(blockNumber, 10); + } else { + const blockTimestamp = (await ethers.provider.getBlock("latest")).timestamp; + expect(await vWBTC.getBlockNumberOrTimestamp()).to.closeTo(blockTimestamp, 10); + } - expect(2).to.be.equal(await vWBTC.version()); + expect(2).to.be.equal(await vWBTC.version()); + }); }); -}); +} diff --git a/tests/hardhat/WhitePaperInterestRateModel.ts b/tests/hardhat/WhitePaperInterestRateModel.ts index 5305db9ff..07caa4cb6 100644 --- a/tests/hardhat/WhitePaperInterestRateModel.ts +++ b/tests/hardhat/WhitePaperInterestRateModel.ts @@ -4,80 +4,91 @@ import BigNumber from "bignumber.js"; import chai from "chai"; import { ethers } from "hardhat"; +import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; import { convertToUnit } from "../../helpers/utils"; import { WhitePaperInterestRateModel } from "../../typechain"; +import { getDescription } from "./util/descriptionHelpers"; const { expect } = chai; chai.use(smock.matchers); -describe("White paper interest rate model tests", () => { - let whitePaperInterestRateModel: WhitePaperInterestRateModel; +for (const isTimeBased of [false, true]) { + let interestRateModel: WhitePaperInterestRateModel; const cash = convertToUnit(10, 19); const borrows = convertToUnit(4, 19); const reserves = convertToUnit(2, 19); const badDebt = convertToUnit(1, 19); const expScale = convertToUnit(1, 18); - const blocksPerYear = 10512000; const baseRatePerYear = convertToUnit(2, 12); const multiplierPerYear = convertToUnit(4, 14); + const description: string = getDescription(isTimeBased); + const slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; - const fixture = async () => { - const WhitePaperInterestRateModelFactory = await ethers.getContractFactory("WhitePaperInterestRateModel"); - whitePaperInterestRateModel = await WhitePaperInterestRateModelFactory.deploy(baseRatePerYear, multiplierPerYear); - await whitePaperInterestRateModel.deployed(); - }; + describe(`${description}White Paper interest rate model tests`, () => { + const fixture = async () => { + const interestRateModelFactory = await ethers.getContractFactory("WhitePaperInterestRateModel"); + interestRateModel = await interestRateModelFactory.deploy( + baseRatePerYear, + multiplierPerYear, + isTimeBased, + slotsPerYear, + ); + await interestRateModel.deployed(); + }; - before(async () => { - await loadFixture(fixture); - }); + before(async () => { + await loadFixture(fixture); + }); - it("Model getters", async () => { - const baseRatePerBlock = new BigNumber(baseRatePerYear).dividedBy(blocksPerYear).toFixed(0); - const multiplierPerBlock = new BigNumber(multiplierPerYear).dividedBy(blocksPerYear).toFixed(0); + it("Model getters", async () => { + const baseRatePerBlockOrTimestamp = new BigNumber(baseRatePerYear).dividedBy(slotsPerYear).toFixed(0); + const multiplierPerBlockOrTimestamp = new BigNumber(multiplierPerYear).dividedBy(slotsPerYear).toFixed(0); - expect(await whitePaperInterestRateModel.baseRatePerBlock()).equal(baseRatePerBlock); - expect(await whitePaperInterestRateModel.multiplierPerBlock()).equal(multiplierPerBlock); - }); + expect(await interestRateModel.baseRatePerBlock()).equal(baseRatePerBlockOrTimestamp); + expect(await interestRateModel.multiplierPerBlock()).equal(multiplierPerBlockOrTimestamp); + }); - it("Utilization rate: borrows and badDebt is zero", async () => { - expect(await whitePaperInterestRateModel.utilizationRate(cash, 0, badDebt, 0)).equal(0); - }); + it("Utilization rate: borrows and badDebt is zero", async () => { + expect(await interestRateModel.utilizationRate(cash, 0, badDebt, 0)).equal(0); + }); - it("Utilization rate", async () => { - const utilizationRate = new BigNumber(Number(borrows) + Number(badDebt)) - .multipliedBy(expScale) - .dividedBy(Number(cash) + Number(borrows) + Number(badDebt) - Number(reserves)) - .toFixed(0); + it("Utilization rate", async () => { + const utilizationRate = new BigNumber(Number(borrows) + Number(badDebt)) + .multipliedBy(expScale) + .dividedBy(Number(cash) + Number(borrows) + Number(badDebt) - Number(reserves)) + .toFixed(0); - expect(await whitePaperInterestRateModel.utilizationRate(cash, borrows, reserves, badDebt)).equal(utilizationRate); - }); + expect(await interestRateModel.utilizationRate(cash, borrows, reserves, badDebt)).equal(utilizationRate); + }); - it("Borrow Rate", async () => { - const multiplierPerBlock = (await whitePaperInterestRateModel.multiplierPerBlock()).toString(); - const baseRatePerBlock = (await whitePaperInterestRateModel.baseRatePerBlock()).toString(); - const utilizationRate = ( - await whitePaperInterestRateModel.utilizationRate(cash, borrows, reserves, badDebt) - ).toString(); + it("Borrow Rate", async () => { + const multiplierPerBlockOrTimestamp = (await interestRateModel.multiplierPerBlock()).toString(); + const baseRatePerBlockOrTimestamp = (await interestRateModel.baseRatePerBlock()).toString(); + const utilizationRate = (await interestRateModel.utilizationRate(cash, borrows, reserves, badDebt)).toString(); - const value = new BigNumber(utilizationRate).multipliedBy(multiplierPerBlock).dividedBy(expScale).toFixed(0); + const value = new BigNumber(utilizationRate) + .multipliedBy(multiplierPerBlockOrTimestamp) + .dividedBy(expScale) + .toFixed(0); - expect(await whitePaperInterestRateModel.getBorrowRate(cash, borrows, reserves, badDebt)).equal( - Number(value) + Number(baseRatePerBlock), - ); - }); + expect(await interestRateModel.getBorrowRate(cash, borrows, reserves, badDebt)).equal( + Number(value) + Number(baseRatePerBlockOrTimestamp), + ); + }); - it("Supply Rate", async () => { - const reserveMantissa = convertToUnit(1, 17); - const oneMinusReserveFactor = Number(expScale) - Number(reserveMantissa); - const borrowRate = (await whitePaperInterestRateModel.getBorrowRate(cash, borrows, reserves, badDebt)).toString(); - const rateToPool = new BigNumber(borrowRate).multipliedBy(oneMinusReserveFactor).dividedBy(expScale).toFixed(0); - const rate = new BigNumber(borrows) - .multipliedBy(expScale) - .dividedBy(Number(cash) + Number(borrows) + Number(badDebt) - Number(reserves)); - const supplyRate = new BigNumber(rateToPool).multipliedBy(rate).dividedBy(expScale).toFixed(0); + it("Supply Rate", async () => { + const reserveMantissa = convertToUnit(1, 17); + const oneMinusReserveFactor = Number(expScale) - Number(reserveMantissa); + const borrowRate = (await interestRateModel.getBorrowRate(cash, borrows, reserves, badDebt)).toString(); + const rateToPool = new BigNumber(borrowRate).multipliedBy(oneMinusReserveFactor).dividedBy(expScale).toFixed(0); + const rate = new BigNumber(borrows) + .multipliedBy(expScale) + .dividedBy(Number(cash) + Number(borrows) + Number(badDebt) - Number(reserves)); + const supplyRate = new BigNumber(rateToPool).multipliedBy(rate).dividedBy(expScale).toFixed(0); - expect( - await whitePaperInterestRateModel.getSupplyRate(cash, borrows, reserves, convertToUnit(1, 17), badDebt), - ).equal(supplyRate); + expect(await interestRateModel.getSupplyRate(cash, borrows, reserves, convertToUnit(1, 17), badDebt)).equal( + supplyRate, + ); + }); }); -}); +} diff --git a/tests/hardhat/util/TokenTestHelpers.ts b/tests/hardhat/util/TokenTestHelpers.ts index 2f789f287..8ec6699a0 100644 --- a/tests/hardhat/util/TokenTestHelpers.ts +++ b/tests/hardhat/util/TokenTestHelpers.ts @@ -4,6 +4,7 @@ import { BigNumber, BigNumberish, Signer } from "ethers"; import { parseUnits } from "ethers/lib/utils"; import { ethers, upgrades } from "hardhat"; +import { BSC_BLOCKS_PER_YEAR } from "../../../helpers/deploymentConfig"; import { AccessControlManager, Comptroller, @@ -34,6 +35,8 @@ interface VTokenParameters { protocolShareReserve: AddressOrContract; reserveFactorMantissa: BigNumberish; beacon: UpgradeableBeacon; + isTimeBased: boolean; + blocksPerYear: BigNumberish; } const getNameAndSymbol = async (underlying: AddressOrContract): Promise<[string, string]> => { @@ -71,9 +74,13 @@ export type AnyVTokenFactory = VTokenHarness__factory | VToken__factory; export const deployVTokenBeacon = async ( { kind }: { kind: string } = { kind: "VToken" }, + isTimeBased: boolean = false, + blocksPerYear: BigNumberish = BSC_BLOCKS_PER_YEAR, ): Promise => { const VToken = await ethers.getContractFactory(kind); - const vTokenBeacon = (await upgrades.deployBeacon(VToken)) as UpgradeableBeacon; + const vTokenBeacon = (await upgrades.deployBeacon(VToken, { + constructorArgs: [isTimeBased, blocksPerYear], + })) as UpgradeableBeacon; return vTokenBeacon; }; @@ -99,7 +106,15 @@ const deployVTokenDependencies = async ({ kind })), + beacon: + params.beacon || + (await deployVTokenBeacon( + { kind }, + params.isTimeBased || false, + params.blocksPerYear || BSC_BLOCKS_PER_YEAR, + )), + isTimeBased: params.isTimeBased || false, + blocksPerYear: params.blocksPerYear || BSC_BLOCKS_PER_YEAR, }; }; diff --git a/tests/hardhat/util/descriptionHelpers.ts b/tests/hardhat/util/descriptionHelpers.ts new file mode 100644 index 000000000..5b0c61998 --- /dev/null +++ b/tests/hardhat/util/descriptionHelpers.ts @@ -0,0 +1,6 @@ +export function getDescription(isTimeBased: boolean) { + if (!isTimeBased) { + return ""; + } + return "TimeBased "; +} diff --git a/tests/integration/index.ts b/tests/integration/index.ts index 7d88f4a79..9371f2568 100644 --- a/tests/integration/index.ts +++ b/tests/integration/index.ts @@ -23,6 +23,14 @@ import { Error } from "../hardhat/util/Errors"; const { expect } = chai; chai.use(smock.matchers); +const timeBasedIntegrationTests = network.config.isTimeBased; +let description: string = "block-based contracts"; + +if (timeBasedIntegrationTests) { + description = "time-based contracts"; +} +console.log(`integration tests are running for ${description}`); + const toggleMining = async (status: boolean) => { if (!status) { await network.provider.send("evm_setAutomine", [false]); @@ -31,7 +39,7 @@ const toggleMining = async (status: boolean) => { } }; -const setupTest = deployments.createFixture(async ({ deployments, getNamedAccounts, ethers }: any) => { +const setupTest = deployments.createFixture(async ({ deployments, getNamedAccounts, ethers }) => { await deployments.fixture(); const { deployer, acc1, acc2, acc3 } = await getNamedAccounts(); const PoolRegistry: PoolRegistry = await ethers.getContract("PoolRegistry"); @@ -377,7 +385,11 @@ describe("Positive Cases", function () { await vBTCB.connect(acc2Signer).borrow(BTCBBorrowAmount); // Mining blocks - await mine(300000000); + if (timeBasedIntegrationTests) { + await mine(700000000); + } else { + await mine(300000000); + } await BTCB.connect(acc1Signer).approve(vBTCB.address, convertToUnit(10, 18)); await Comptroller.connect(acc1Signer).healAccount(acc2); @@ -497,7 +509,11 @@ describe("Straight Cases For Single User Liquidation and healing", function () { ); await Comptroller.setPriceOracle(dummyPriceOracle.address); + const repayAmount = convertToUnit("1000000000007133", 0); + // if (timeBasedIntegrationTests) { + // repayAmount = convertToUnit("1000000000002377", 0); + // } const param = { vTokenCollateral: vBNX.address, vTokenBorrowed: vBTCB.address, diff --git a/yarn.lock b/yarn.lock index 194f5646b..010d88e14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2156,6 +2156,13 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/contracts@npm:4.9.3": + version: 4.9.3 + resolution: "@openzeppelin/contracts@npm:4.9.3" + checksum: 4932063e733b35fa7669b9fe2053f69b062366c5c208b0c6cfa1ac451712100c78acff98120c3a4b88d94154c802be05d160d71f37e7d74cadbe150964458838 + languageName: node + linkType: hard + "@openzeppelin/contracts@npm:^4.3.3, @openzeppelin/contracts@npm:^4.6.0, @openzeppelin/contracts@npm:^4.8.3": version: 4.9.2 resolution: "@openzeppelin/contracts@npm:4.9.2" @@ -2934,17 +2941,17 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/governance-contracts@npm:^0.0.2": - version: 0.0.2 - resolution: "@venusprotocol/governance-contracts@npm:0.0.2" - checksum: 101ade6013fe3963968d37ff839a4c62aeaedd9f26d8c5ae47bdc413e6c61732b4048a1b026e4281ade5676fb1545a49ecac299f6b669a9f0c7e73723666d7e1 +"@venusprotocol/governance-contracts@npm:1.4.0-dev.2, @venusprotocol/governance-contracts@npm:^1.4.0-dev.1": + version: 1.4.0-dev.2 + resolution: "@venusprotocol/governance-contracts@npm:1.4.0-dev.2" + checksum: eea8efe2ef9bf1165d4f639049015d2acd8a1d98f643bb50c59f5b4c93762833709411c2d32b82e9be662f64a61605b4186fcacad44bd227c934f4b55f801880 languageName: node linkType: hard -"@venusprotocol/governance-contracts@npm:^1.0.0": - version: 1.0.0 - resolution: "@venusprotocol/governance-contracts@npm:1.0.0" - checksum: 8df88f2e702da976861f6e409ab109dec24f8ac4e4e049da505ee36d36af6c2478bb4b6a2f3401f360578bd167512cb016227526bf81ebfdf3ca91ef473e7f87 +"@venusprotocol/governance-contracts@npm:^1.3.0": + version: 1.3.0 + resolution: "@venusprotocol/governance-contracts@npm:1.3.0" + checksum: 9cbc44e5fffd2f33e273c96e3f77b2d9afe254b3f8c22533eecb96f79011715afafd72f2a716bab5509164fa4f3e0629b94450f16619bba221d8d5a9e632b610 languageName: node linkType: hard @@ -2975,10 +2982,10 @@ __metadata: "@types/node": ^12.20.50 "@typescript-eslint/eslint-plugin": ^5.27.1 "@typescript-eslint/parser": ^5.27.1 - "@venusprotocol/governance-contracts": ^1.0.0 - "@venusprotocol/oracle": 1.7.2 - "@venusprotocol/protocol-reserve": ^1.1.0-dev.1 - "@venusprotocol/venus-protocol": 3.0.0-dev.18 + "@venusprotocol/governance-contracts": 1.4.0-dev.2 + "@venusprotocol/oracle": 1.8.0-dev.3 + "@venusprotocol/protocol-reserve": 1.2.0-dev.2 + "@venusprotocol/venus-protocol": 6.0.1-dev.2 bignumber.js: 9.0.0 chai: ^4.3.6 dotenv: ^10.0.0 @@ -3008,29 +3015,29 @@ __metadata: languageName: unknown linkType: soft -"@venusprotocol/oracle@npm:1.7.2": - version: 1.7.2 - resolution: "@venusprotocol/oracle@npm:1.7.2" +"@venusprotocol/oracle@npm:1.8.0-dev.3": + version: 1.8.0-dev.3 + resolution: "@venusprotocol/oracle@npm:1.8.0-dev.3" dependencies: "@chainlink/contracts": ^0.5.1 "@defi-wonderland/smock": ^2.3.4 "@nomicfoundation/hardhat-network-helpers": ^1.0.8 "@openzeppelin/contracts": ^4.6.0 "@openzeppelin/contracts-upgradeable": ^4.7.3 - "@venusprotocol/governance-contracts": ^0.0.2 + "@venusprotocol/governance-contracts": ^1.3.0 "@venusprotocol/venus-protocol": 0.7.0 ethers: ^5.6.8 hardhat: ^2.16.1 hardhat-deploy: ^0.11.14 module-alias: ^2.2.2 solidity-docgen: ^0.6.0-beta.29 - checksum: 71dc7faf761e110cda526dabbe2ac7bdda40849cccb6473647cf80edd6940e1cbe02528c270f83e9d14c7815cdfaf736a1acef3c8896cf04926f72a8c53ff9df + checksum: 2cdb3a96c5566e317636bb240d61356edbb19534be3c7f745920e2d4737aa2ccb21ad5ea35cd0d2668d2d64b28b789d8b5801e0102ae55a7e4b70ab5db1de6eb languageName: node linkType: hard -"@venusprotocol/protocol-reserve@npm:^1.1.0-dev.1": - version: 1.1.0-dev.1 - resolution: "@venusprotocol/protocol-reserve@npm:1.1.0-dev.1" +"@venusprotocol/protocol-reserve@npm:1.2.0-dev.2": + version: 1.2.0-dev.2 + resolution: "@venusprotocol/protocol-reserve@npm:1.2.0-dev.2" dependencies: "@nomiclabs/hardhat-ethers": ^2.2.3 "@openzeppelin/contracts": ^4.8.3 @@ -3041,7 +3048,7 @@ __metadata: ethers: ^5.7.0 hardhat-deploy: ^0.11.14 module-alias: ^2.2.2 - checksum: 3d50f13cbfc0314924178454a59bb991b41c7c402eb9b6befdf68efe94d0e5124373f786f2cb50dc083b45daa895487d74062bddebbe2d772e19a0e1eb58a77a + checksum: e644bc58b6b4646ce6b262e9e34646d65285dee97cb38a34ac99d35330b3f4bea4c9075d87ee6e6d1e813563c622a01e12eba82014e6d7952e17ea798673bac3 languageName: node linkType: hard @@ -3064,17 +3071,18 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/venus-protocol@npm:3.0.0-dev.18": - version: 3.0.0-dev.18 - resolution: "@venusprotocol/venus-protocol@npm:3.0.0-dev.18" +"@venusprotocol/venus-protocol@npm:6.0.1-dev.2": + version: 6.0.1-dev.2 + resolution: "@venusprotocol/venus-protocol@npm:6.0.1-dev.2" dependencies: - "@openzeppelin/contracts": ^4.8.3 + "@openzeppelin/contracts": 4.9.3 "@openzeppelin/contracts-upgradeable": ^4.8.0 + "@venusprotocol/governance-contracts": ^1.4.0-dev.1 + "@venusprotocol/protocol-reserve": 1.2.0-dev.2 + bignumber.js: ^9.1.2 dotenv: ^16.0.1 module-alias: ^2.2.2 - peerDependencies: - hardhat: ^2.10.1 - checksum: 1545bba019602a9072474809461a9a20cbb465b108b0567716891ee5c4d457fa56eb14919bfce58fa314b0e21e7857a1375670f96161e0e7e2d2c1422ffff3e1 + checksum: 0b1da169b6ddd1799f2d2d9667d61ced50244acdad68588cb84b051e89ebeb8940a28db9fc890d9b499bd8fc6f774c4163b3bcd0a2a8d2a75080c9c0af80d2e9 languageName: node linkType: hard @@ -3810,6 +3818,13 @@ __metadata: languageName: node linkType: hard +"bignumber.js@npm:^9.1.2": + version: 9.1.2 + resolution: "bignumber.js@npm:9.1.2" + checksum: 582c03af77ec9cb0ebd682a373ee6c66475db94a4325f92299621d544aa4bd45cb45fd60001610e94aef8ae98a0905fa538241d9638d4422d57abbeeac6fadaf + languageName: node + linkType: hard + "bin-links@npm:^3.0.3": version: 3.0.3 resolution: "bin-links@npm:3.0.3" From d6aeca8a26784b89e33ab18752d62c43b3e02575 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 4 Dec 2023 17:48:16 +0530 Subject: [PATCH 02/22] refactor: update getBlockOrTimestampBasedDeploymentInfo function --- .env.example | 3 +++ deploy/007-deploy-pool-lens.ts | 2 +- deploy/009-deploy-vtokens.ts | 2 +- deploy/010-deploy-reward-distributors.ts | 2 +- deploy/014-riskfund-protocolshare.ts | 2 +- hardhat.config.ts | 5 ----- helpers/deploymentConfig.ts | 2 -- helpers/deploymentUtils.ts | 6 +++--- tests/integration/index.ts | 5 +++-- 9 files changed, 13 insertions(+), 16 deletions(-) diff --git a/.env.example b/.env.example index 6b9d97696..5fc6eff30 100644 --- a/.env.example +++ b/.env.example @@ -20,3 +20,6 @@ ETHERSCAN_API_KEY= # Set to true or false to control gas reporting REPORT_GAS= + +# Set to true or false to deploy contracts based on timestamp or block +IS_TIME_BASED_DEPLOYMENT=false \ No newline at end of file diff --git a/deploy/007-deploy-pool-lens.ts b/deploy/007-deploy-pool-lens.ts index f5c564d01..2ccd22246 100644 --- a/deploy/007-deploy-pool-lens.ts +++ b/deploy/007-deploy-pool-lens.ts @@ -8,7 +8,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deploy } = deployments; const { deployer } = await getNamedAccounts(); - const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre); + const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.network.name); await deploy("PoolLens", { from: deployer, diff --git a/deploy/009-deploy-vtokens.ts b/deploy/009-deploy-vtokens.ts index f05b93039..9a90a76ab 100644 --- a/deploy/009-deploy-vtokens.ts +++ b/deploy/009-deploy-vtokens.ts @@ -20,7 +20,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployer } = await getNamedAccounts(); const { tokensConfig, poolConfig, preconfiguredAddresses } = await getConfig(hre.network.name); - const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre); + const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.network.name); const accessControlManagerAddress = await toAddress( preconfiguredAddresses.AccessControlManager || "AccessControlManager", diff --git a/deploy/010-deploy-reward-distributors.ts b/deploy/010-deploy-reward-distributors.ts index 78e919cab..21519b9dc 100644 --- a/deploy/010-deploy-reward-distributors.ts +++ b/deploy/010-deploy-reward-distributors.ts @@ -16,7 +16,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const maxLoopsLimit = 100; const { tokensConfig, poolConfig, preconfiguredAddresses } = await getConfig(hre.network.name); - const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre); + const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.network.name); const accessControlAddress = await toAddress( preconfiguredAddresses.AccessControlManager || "AccessControlManager", diff --git a/deploy/014-riskfund-protocolshare.ts b/deploy/014-riskfund-protocolshare.ts index b645ffee8..49d75280c 100644 --- a/deploy/014-riskfund-protocolshare.ts +++ b/deploy/014-riskfund-protocolshare.ts @@ -19,7 +19,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { tokensConfig, preconfiguredAddresses } = await getConfig(hre.network.name); const usdt = await getUnderlyingToken("USDT", tokensConfig); - const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre); + const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.network.name); const poolRegistry = await ethers.getContract("PoolRegistry"); const deployerSigner = ethers.provider.getSigner(deployer); diff --git a/hardhat.config.ts b/hardhat.config.ts index a691fbfb4..5f7804af3 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -162,7 +162,6 @@ const config: HardhatUserConfig = { chainId: 97, live: true, gasPrice: 20000000000, - isTimeBased: false, accounts: process.env.DEPLOYER_PRIVATE_KEY ? [`0x${process.env.DEPLOYER_PRIVATE_KEY}`] : [], }, // Mainnet deployments are done through Frame wallet RPC @@ -170,7 +169,6 @@ const config: HardhatUserConfig = { url: process.env.ARCHIVE_NODE_bscmainnet || "https://bsc-dataseed.binance.org/", chainId: 56, timeout: 1200000, - isTimeBased: false, accounts: { mnemonic: process.env.MNEMONIC || "", }, @@ -180,7 +178,6 @@ const config: HardhatUserConfig = { chainId: 11155111, live: true, timeout: 1200000, // 20 minutes, - isTimeBased: false, accounts: process.env.DEPLOYER_PRIVATE_KEY ? [`0x${process.env.DEPLOYER_PRIVATE_KEY}`] : [], }, ethereum: { @@ -188,7 +185,6 @@ const config: HardhatUserConfig = { chainId: 1, live: true, timeout: 1200000, // 20 minutes, - isTimeBased: false, accounts: process.env.DEPLOYER_PRIVATE_KEY ? [`0x${process.env.DEPLOYER_PRIVATE_KEY}`] : [], }, }, @@ -299,7 +295,6 @@ function isFork() { allowUnlimitedContractSize: true, loggingEnabled: false, live: false, - isTimeBased: false, }; } export default config; diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 7e3b61600..54fd9938f 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -17,8 +17,6 @@ export type NetworkConfig = { bscmainnet: DeploymentConfig; sepolia: DeploymentConfig; ethereum: DeploymentConfig; - sepolia: DeploymentConfig; - ethereum: DeploymentConfig; }; export type PreconfiguredAddresses = { [contract: string]: string }; diff --git a/helpers/deploymentUtils.ts b/helpers/deploymentUtils.ts index 6f9c0533a..38f017cfc 100644 --- a/helpers/deploymentUtils.ts +++ b/helpers/deploymentUtils.ts @@ -135,9 +135,9 @@ export const getUnregisteredRewardsDistributors = async ( ); }; -export const getBlockOrTimestampBasedDeploymentInfo = (hre: any): DeploymentInfo => { - const isTimeBased = hre.network.config.isTimeBased; - const blocksPerYearKey = isTimeBased ? "isTimeBased" : hre.network.name; +export const getBlockOrTimestampBasedDeploymentInfo = (network: string): DeploymentInfo => { + const isTimeBased = process.env.IS_TIME_BASED_DEPLOYMENT === "true"; + const blocksPerYearKey = isTimeBased ? "isTimeBased" : network; return { isTimeBased: isTimeBased, blocksPerYear: blocksPerYear[blocksPerYearKey] }; }; diff --git a/tests/integration/index.ts b/tests/integration/index.ts index 4d6a9ba01..0d0fa88f5 100644 --- a/tests/integration/index.ts +++ b/tests/integration/index.ts @@ -23,7 +23,7 @@ import { Error } from "../hardhat/util/Errors"; const { expect } = chai; chai.use(smock.matchers); -const timeBasedIntegrationTests = network.config.isTimeBased; +const timeBasedIntegrationTests = process.env.IS_TIME_BASED_DEPLOYMENT === "true"; let description: string = "block-based contracts"; if (timeBasedIntegrationTests) { @@ -510,7 +510,8 @@ describe("Straight Cases For Single User Liquidation and healing", function () { await Comptroller.setPriceOracle(dummyPriceOracle.address); - const repayAmount = convertToUnit("1000000000007133", 0); + let repayAmount = 1000000000007133; + if (timeBasedIntegrationTests) repayAmount = 1000000000002377; const param = { vTokenCollateral: vBNX.address, vTokenBorrowed: vBTCB.address, From 2534ca7507a01e9c5eb21fe75671acd53e87dc54 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Thu, 21 Dec 2023 18:02:41 +0530 Subject: [PATCH 03/22] refactor: removed TimeManager contract --- contracts/JumpRateModelV2.sol | 6 +- contracts/Lens/PoolLens.sol | 6 +- contracts/Rewards/RewardsDistributor.sol | 6 +- contracts/Shortfall/Shortfall.sol | 6 +- contracts/TimeManager.sol | 60 -------------------- contracts/VToken.sol | 6 +- contracts/WhitePaperInterestRateModel.sol | 6 +- package.json | 1 + tests/hardhat/JumpRateModelV2.ts | 3 +- tests/hardhat/Lens/PoolLens.ts | 8 +-- tests/hardhat/Lens/RewardsSummary.ts | 4 +- tests/hardhat/Rewards.ts | 4 +- tests/hardhat/Shortfall.ts | 4 +- tests/hardhat/UpgradedVToken.ts | 4 +- tests/hardhat/WhitePaperInterestRateModel.ts | 3 +- tests/hardhat/util/TokenTestHelpers.ts | 6 +- yarn.lock | 8 +++ 17 files changed, 45 insertions(+), 96 deletions(-) delete mode 100644 contracts/TimeManager.sol diff --git a/contracts/JumpRateModelV2.sol b/contracts/JumpRateModelV2.sol index f458151df..9999e8b6c 100644 --- a/contracts/JumpRateModelV2.sol +++ b/contracts/JumpRateModelV2.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.13; import { IAccessControlManagerV8 } from "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol"; -import { TimeManager } from "./TimeManager.sol"; +import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; import { InterestRateModel } from "./InterestRateModel.sol"; import { EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; @@ -12,7 +12,7 @@ import { EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached. * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters */ -contract JumpRateModelV2 is TimeManager, InterestRateModel { +contract JumpRateModelV2 is TimeManagerV8, InterestRateModel { /** * @notice The address of the AccessControlManager contract */ @@ -68,7 +68,7 @@ contract JumpRateModelV2 is TimeManager, InterestRateModel { IAccessControlManagerV8 accessControlManager_, bool timeBased_, uint256 blocksPerYear_ - ) TimeManager(timeBased_, blocksPerYear_) { + ) TimeManagerV8(timeBased_, blocksPerYear_) { require(address(accessControlManager_) != address(0), "invalid ACM address"); accessControlManager = accessControlManager_; diff --git a/contracts/Lens/PoolLens.sol b/contracts/Lens/PoolLens.sol index 206c2f3d0..81a6cfff3 100644 --- a/contracts/Lens/PoolLens.sol +++ b/contracts/Lens/PoolLens.sol @@ -11,7 +11,7 @@ import { ComptrollerInterface, ComptrollerViewInterface } from "../ComptrollerIn import { PoolRegistryInterface } from "../Pool/PoolRegistryInterface.sol"; import { PoolRegistry } from "../Pool/PoolRegistry.sol"; import { RewardsDistributor } from "../Rewards/RewardsDistributor.sol"; -import { TimeManager } from "../TimeManager.sol"; +import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; /** * @title PoolLens @@ -26,7 +26,7 @@ import { TimeManager } from "../TimeManager.sol"; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken. */ -contract PoolLens is TimeManager, ExponentialNoError { +contract PoolLens is TimeManagerV8, ExponentialNoError { /** * @dev Struct for PoolDetails. */ @@ -140,7 +140,7 @@ contract PoolLens is TimeManager, ExponentialNoError { * @param blocksPerYear_ The number of blocks per year * @custom:oz-upgrades-unsafe-allow constructor */ - constructor(bool timeBased_, uint256 blocksPerYear_) TimeManager(timeBased_, blocksPerYear_) {} + constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {} /** * @notice Queries the user's supply/borrow balances in vTokens diff --git a/contracts/Rewards/RewardsDistributor.sol b/contracts/Rewards/RewardsDistributor.sol index cde1a0d8a..938ca8769 100644 --- a/contracts/Rewards/RewardsDistributor.sol +++ b/contracts/Rewards/RewardsDistributor.sol @@ -10,7 +10,7 @@ import { ExponentialNoError } from "../ExponentialNoError.sol"; import { VToken } from "../VToken.sol"; import { Comptroller } from "../Comptroller.sol"; import { MaxLoopsLimitHelper } from "../MaxLoopsLimitHelper.sol"; -import { TimeManager } from "../TimeManager.sol"; +import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; /** * @title `RewardsDistributor` @@ -28,7 +28,7 @@ import { TimeManager } from "../TimeManager.sol"; * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors. */ contract RewardsDistributor is - TimeManager, + TimeManagerV8, ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, @@ -158,7 +158,7 @@ contract RewardsDistributor is * @param blocksPerYear_ The number of blocks per year * @custom:oz-upgrades-unsafe-allow constructor */ - constructor(bool timeBased_, uint256 blocksPerYear_) TimeManager(timeBased_, blocksPerYear_) { + constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) { // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. _disableInitializers(); diff --git a/contracts/Shortfall/Shortfall.sol b/contracts/Shortfall/Shortfall.sol index 4f3c51ffc..0d5c96b39 100644 --- a/contracts/Shortfall/Shortfall.sol +++ b/contracts/Shortfall/Shortfall.sol @@ -8,7 +8,7 @@ import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/ import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol"; import { VToken } from "../VToken.sol"; -import { TimeManager } from "../TimeManager.sol"; +import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; import { ComptrollerInterface, ComptrollerViewInterface } from "../ComptrollerInterface.sol"; import { IRiskFund } from "../RiskFund/IRiskFund.sol"; import { PoolRegistry } from "../Pool/PoolRegistry.sol"; @@ -28,7 +28,7 @@ import { EXP_SCALE } from "../lib/constants.sol"; * risk fund in exchange for paying off all the pool's bad debt. */ contract Shortfall is - TimeManager, + TimeManagerV8, Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGuardUpgradeable, @@ -170,7 +170,7 @@ contract Shortfall is * @param blocksPerYear_ The number of blocks per year * @custom:oz-upgrades-unsafe-allow constructor */ - constructor(bool timeBased_, uint256 blocksPerYear_) TimeManager(timeBased_, blocksPerYear_) { + constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) { // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. _disableInitializers(); diff --git a/contracts/TimeManager.sol b/contracts/TimeManager.sol deleted file mode 100644 index b8d4585a5..000000000 --- a/contracts/TimeManager.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -pragma solidity 0.8.13; - -import { SECONDS_PER_YEAR } from "./lib/constants.sol"; - -abstract contract TimeManager { - /// @custom:oz-upgrades-unsafe-allow state-variable-immutable - uint256 public immutable blocksOrSecondsPerYear; - - /// @custom:oz-upgrades-unsafe-allow state-variable-immutable - bool public immutable isTimeBased; - - /// @custom:oz-upgrades-unsafe-allow state-variable-immutable - function() view returns (uint256) private immutable _getCurrentSlot; - - /// @notice Thrown on invaid arguments - error InvalidBlocksPerYear(); - - /** - * @param timeBased_ A boolean indicating whether the contract is based on time or block. - * If timeBased is true than blocksPerYear_ param is ignored as blocksOrSecondsPerYear is set to SECONDS_PER_YEAR - * @param blocksPerYear_ The number of blocks per year - * @custom:error InvalidBlocksPerYear is thrown if blocksPerYear entered is zero - * @custom:oz-upgrades-unsafe-allow constructor - */ - constructor(bool timeBased_, uint256 blocksPerYear_) { - if (!timeBased_ && blocksPerYear_ == 0) { - revert InvalidBlocksPerYear(); - } - - isTimeBased = timeBased_; - blocksOrSecondsPerYear = timeBased_ ? SECONDS_PER_YEAR : blocksPerYear_; - _getCurrentSlot = timeBased_ ? _getBlockTimestamp : _getBlockNumber; - } - - /** - * @dev Function to simply retrieve block number or block timestamp - * This exists mainly for inheriting test contracts to stub this result. - * @return Current block number or block timestamp - */ - function getBlockNumberOrTimestamp() public view virtual returns (uint256) { - return _getCurrentSlot(); - } - - /** - * @notice Returns the current timestamp in seconds - * @return The current timestamp - */ - function _getBlockTimestamp() private view returns (uint256) { - return block.timestamp; - } - - /** - * @notice Returns the current block number - * @return The current block number - */ - function _getBlockNumber() private view returns (uint256) { - return block.number; - } -} diff --git a/contracts/VToken.sol b/contracts/VToken.sol index fde2e3a67..ecc21ee46 100644 --- a/contracts/VToken.sol +++ b/contracts/VToken.sol @@ -12,7 +12,7 @@ import { ComptrollerInterface, ComptrollerViewInterface } from "./ComptrollerInt import { TokenErrorReporter } from "./ErrorReporter.sol"; import { InterestRateModel } from "./InterestRateModel.sol"; import { ExponentialNoError } from "./ExponentialNoError.sol"; -import { TimeManager } from "./TimeManager.sol"; +import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; import { ensureNonzeroAddress } from "./lib/validators.sol"; /** @@ -42,7 +42,7 @@ import { ensureNonzeroAddress } from "./lib/validators.sol"; * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below. */ contract VToken is - TimeManager, + TimeManagerV8, Ownable2StepUpgradeable, AccessControlledV8, VTokenInterface, @@ -72,7 +72,7 @@ contract VToken is * @param blocksPerYear_ The number of blocks per year * @custom:oz-upgrades-unsafe-allow constructor */ - constructor(bool timeBased_, uint256 blocksPerYear_) TimeManager(timeBased_, blocksPerYear_) { + constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) { // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. _disableInitializers(); diff --git a/contracts/WhitePaperInterestRateModel.sol b/contracts/WhitePaperInterestRateModel.sol index fe4c880db..d578b0418 100644 --- a/contracts/WhitePaperInterestRateModel.sol +++ b/contracts/WhitePaperInterestRateModel.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.13; import { InterestRateModel } from "./InterestRateModel.sol"; -import { TimeManager } from "./TimeManager.sol"; +import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; import { EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; /** @@ -10,7 +10,7 @@ import { EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; * @author Compound * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper */ -contract WhitePaperInterestRateModel is TimeManager, InterestRateModel { +contract WhitePaperInterestRateModel is TimeManagerV8, InterestRateModel { /** * @notice The multiplier of utilization rate per block or second that gives the slope of the interest rate */ @@ -35,7 +35,7 @@ contract WhitePaperInterestRateModel is TimeManager, InterestRateModel { uint256 multiplierPerYear_, bool timeBased_, uint256 blocksPerYear_ - ) TimeManager(timeBased_, blocksPerYear_) { + ) TimeManagerV8(timeBased_, blocksPerYear_) { baseRatePerBlock = baseRatePerYear_ / blocksOrSecondsPerYear; multiplierPerBlock = multiplierPerYear_ / blocksOrSecondsPerYear; diff --git a/package.json b/package.json index f451afa05..641e329d6 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "@openzeppelin/contracts-upgradeable": "^4.8.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", "@solidity-parser/parser": "^0.13.2", + "@venusprotocol/solidity-utilities": "^1.2.0-dev.1", "ethers": "^5.7.0", "hardhat-deploy": "^0.11.14", "module-alias": "^2.2.2" diff --git a/tests/hardhat/JumpRateModelV2.ts b/tests/hardhat/JumpRateModelV2.ts index 3db11c278..afd2c86e9 100644 --- a/tests/hardhat/JumpRateModelV2.ts +++ b/tests/hardhat/JumpRateModelV2.ts @@ -27,7 +27,7 @@ for (const isTimeBased of [false, true]) { const jumpMultiplierPerYear = convertToUnit(2, 18); const description = getDescription(isTimeBased); - const slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; + let slotsPerYear = isTimeBased ? 0 : BSC_BLOCKS_PER_YEAR; describe(`${description}Jump rate model tests`, async () => { const fixture = async () => { @@ -49,6 +49,7 @@ for (const isTimeBased of [false, true]) { before(async () => { await loadFixture(fixture); + slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; }); it("Update jump rate model", async () => { diff --git a/tests/hardhat/Lens/PoolLens.ts b/tests/hardhat/Lens/PoolLens.ts index 82711bc85..37c412779 100644 --- a/tests/hardhat/Lens/PoolLens.ts +++ b/tests/hardhat/Lens/PoolLens.ts @@ -5,7 +5,7 @@ import { BigNumberish, Signer } from "ethers"; import { parseUnits } from "ethers/lib/utils"; import { ethers, upgrades } from "hardhat"; -import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../../helpers/deploymentConfig"; +import { BSC_BLOCKS_PER_YEAR } from "../../../helpers/deploymentConfig"; import { AccessControlManager, Beacon, @@ -48,7 +48,7 @@ const assertVTokenMetadata = (vTokenMetadataActual: any, vTokenMetadataExpected: for (const isTimeBased of [false, true]) { const description = getDescription(isTimeBased); - const slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; + const slotsPerYear = isTimeBased ? 0 : BSC_BLOCKS_PER_YEAR; describe(`${description}PoolLens`, async () => { let poolRegistry: PoolRegistry; @@ -100,7 +100,6 @@ for (const isTimeBased of [false, true]) { ({ poolRegistry, fakeAccessControlManager } = await loadFixture(poolRegistryFixture)); poolRegistryAddress = poolRegistry.address; - const MockPriceOracle = await ethers.getContractFactory("MockPriceOracle"); priceOracle = await MockPriceOracle.deploy(); @@ -141,7 +140,6 @@ for (const isTimeBased of [false, true]) { liquidationIncentive2, minLiquidatableCollateral, ); - const MockToken = await ethers.getContractFactory("MockToken"); mockDAI = await MockToken.deploy("MakerDAO", "DAI", 18); await mockDAI.faucet(parseUnits("1000", 18)); @@ -161,7 +159,6 @@ for (const isTimeBased of [false, true]) { const RateModel = await ethers.getContractFactory( "WhitePaperInterestRateModel", ); - const whitePaperInterestRateModel = await RateModel.deploy(0, parseUnits("0.04", 18), isTimeBased, slotsPerYear); vWBTC = await makeVToken({ underlying: mockWBTC, @@ -227,7 +224,6 @@ for (const isTimeBased of [false, true]) { const vWBTCAddress = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockWBTC.address); const vDAIAddress = await poolRegistry.getVTokenForAsset(comptroller1Proxy.address, mockDAI.address); - vWBTC = await ethers.getContractAt("VToken", vWBTCAddress); vDAI = await ethers.getContractAt("VToken", vDAIAddress); diff --git a/tests/hardhat/Lens/RewardsSummary.ts b/tests/hardhat/Lens/RewardsSummary.ts index 7cf08c11c..0410c1d32 100644 --- a/tests/hardhat/Lens/RewardsSummary.ts +++ b/tests/hardhat/Lens/RewardsSummary.ts @@ -4,7 +4,7 @@ import chai from "chai"; import { BigNumber, Signer } from "ethers"; import { ethers } from "hardhat"; -import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../../helpers/deploymentConfig"; +import { BSC_BLOCKS_PER_YEAR } from "../../../helpers/deploymentConfig"; import { convertToUnit } from "../../../helpers/utils"; import { Comptroller, MockToken, PoolLens, PoolLens__factory, RewardsDistributor, VToken } from "../../../typechain"; import { getDescription } from "../util/descriptionHelpers"; @@ -164,7 +164,7 @@ const timeBasedRewardsFixture = async (): Promise => { const poolLensFactory = await smock.mock("PoolLens"); isTimeBased = true; - blocksPerYear = SECONDS_PER_YEAR; + blocksPerYear = 0; poolLens = await poolLensFactory.deploy(isTimeBased, blocksPerYear); const startBlock = (await ethers.provider.getBlock("latest")).number; diff --git a/tests/hardhat/Rewards.ts b/tests/hardhat/Rewards.ts index 20b6062c6..bc442d4c3 100644 --- a/tests/hardhat/Rewards.ts +++ b/tests/hardhat/Rewards.ts @@ -5,7 +5,7 @@ import { expect } from "chai"; import { parseUnits } from "ethers/lib/utils"; import { ethers, upgrades } from "hardhat"; -import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; +import { BSC_BLOCKS_PER_YEAR } from "../../helpers/deploymentConfig"; import { convertToUnit } from "../../helpers/utils"; import { AccessControlManager, @@ -99,7 +99,7 @@ async function rewardsFixture(isTimeBased: boolean) { ); if (isTimeBased) { - blocksPerYear = SECONDS_PER_YEAR; + blocksPerYear = 0; } // Deploy VTokens diff --git a/tests/hardhat/Shortfall.ts b/tests/hardhat/Shortfall.ts index 2952333a6..3653f28e7 100644 --- a/tests/hardhat/Shortfall.ts +++ b/tests/hardhat/Shortfall.ts @@ -7,7 +7,7 @@ import { constants } from "ethers"; import { parseUnits } from "ethers/lib/utils"; import { ethers, upgrades } from "hardhat"; -import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; +import { BSC_BLOCKS_PER_YEAR } from "../../helpers/deploymentConfig"; import { AddressOne, convertToUnit } from "../../helpers/utils"; import { AccessControlManager, @@ -183,7 +183,7 @@ async function shortfallFixture() { async function timeBasedhortfallFixture() { isTimeBased = true; - blocksPerYear = SECONDS_PER_YEAR; + blocksPerYear = 0; const MockBUSD = await ethers.getContractFactory("MockToken"); mockBUSD = await MockBUSD.deploy("BUSD", "BUSD", 18); await mockBUSD.faucet(convertToUnit(100000, 18)); diff --git a/tests/hardhat/UpgradedVToken.ts b/tests/hardhat/UpgradedVToken.ts index 1d7171ce3..6920741e5 100644 --- a/tests/hardhat/UpgradedVToken.ts +++ b/tests/hardhat/UpgradedVToken.ts @@ -3,7 +3,7 @@ import { expect } from "chai"; import { parseUnits } from "ethers/lib/utils"; import { ethers, upgrades } from "hardhat"; -import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; +import { BSC_BLOCKS_PER_YEAR } from "../../helpers/deploymentConfig"; import { convertToUnit } from "../../helpers/utils"; import { AccessControlManager, @@ -28,7 +28,7 @@ let fakeAccessControlManager: FakeContract; for (const isTimeBased of [false, true]) { const description = getDescription(isTimeBased); - const slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; + const slotsPerYear = isTimeBased ? 0 : BSC_BLOCKS_PER_YEAR; describe(`${description}UpgradedVToken: Tests`, function () { /** diff --git a/tests/hardhat/WhitePaperInterestRateModel.ts b/tests/hardhat/WhitePaperInterestRateModel.ts index 07caa4cb6..f2d83ddf6 100644 --- a/tests/hardhat/WhitePaperInterestRateModel.ts +++ b/tests/hardhat/WhitePaperInterestRateModel.ts @@ -22,7 +22,7 @@ for (const isTimeBased of [false, true]) { const baseRatePerYear = convertToUnit(2, 12); const multiplierPerYear = convertToUnit(4, 14); const description: string = getDescription(isTimeBased); - const slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; + let slotsPerYear = isTimeBased ? 0 : BSC_BLOCKS_PER_YEAR; describe(`${description}White Paper interest rate model tests`, () => { const fixture = async () => { @@ -38,6 +38,7 @@ for (const isTimeBased of [false, true]) { before(async () => { await loadFixture(fixture); + slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; }); it("Model getters", async () => { diff --git a/tests/hardhat/util/TokenTestHelpers.ts b/tests/hardhat/util/TokenTestHelpers.ts index 8ec6699a0..0263ac44b 100644 --- a/tests/hardhat/util/TokenTestHelpers.ts +++ b/tests/hardhat/util/TokenTestHelpers.ts @@ -111,10 +111,10 @@ const deployVTokenDependencies = async ( { kind }, params.isTimeBased || false, - params.blocksPerYear || BSC_BLOCKS_PER_YEAR, + params.blocksPerYear === 0 ? 0 : BSC_BLOCKS_PER_YEAR, )), isTimeBased: params.isTimeBased || false, - blocksPerYear: params.blocksPerYear || BSC_BLOCKS_PER_YEAR, + blocksPerYear: params.blocksPerYear === 0 ? 0 : BSC_BLOCKS_PER_YEAR, }; }; @@ -123,6 +123,7 @@ export const makeVToken = async > => { const params_ = await deployVTokenDependencies(params, { kind }); + const VToken = await ethers.getContractFactory(kind); const vToken = (await upgrades.deployBeaconProxy(params_.beacon, VToken, [ @@ -141,6 +142,7 @@ export const makeVToken = async ; + return vToken; }; diff --git a/yarn.lock b/yarn.lock index 010d88e14..b9dde95a7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2985,6 +2985,7 @@ __metadata: "@venusprotocol/governance-contracts": 1.4.0-dev.2 "@venusprotocol/oracle": 1.8.0-dev.3 "@venusprotocol/protocol-reserve": 1.2.0-dev.2 + "@venusprotocol/solidity-utilities": ^1.2.0-dev.1 "@venusprotocol/venus-protocol": 6.0.1-dev.2 bignumber.js: 9.0.0 chai: ^4.3.6 @@ -3059,6 +3060,13 @@ __metadata: languageName: node linkType: hard +"@venusprotocol/solidity-utilities@npm:^1.2.0-dev.1": + version: 1.2.0-dev.1 + resolution: "@venusprotocol/solidity-utilities@npm:1.2.0-dev.1" + checksum: 0e7958c4dea51cc2d84cdc9039d21e00d265863573fb0d1eab575bd2f9d5b50c80dce60f96213a7d9764f9f7c8a03403e89c838cd3539c75632e66e1f59dcdec + languageName: node + linkType: hard + "@venusprotocol/venus-protocol@npm:0.7.0": version: 0.7.0 resolution: "@venusprotocol/venus-protocol@npm:0.7.0" From c0d60dfbc4bc08f6ae272b8b6090222097a7e329 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Fri, 22 Dec 2023 13:59:07 +0530 Subject: [PATCH 04/22] fix: condition for selection of blocks --- tests/hardhat/JumpRateModelV2.ts | 4 ++-- tests/hardhat/WhitePaperInterestRateModel.ts | 4 ++-- tests/hardhat/util/TokenTestHelpers.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/hardhat/JumpRateModelV2.ts b/tests/hardhat/JumpRateModelV2.ts index afd2c86e9..ba9b69865 100644 --- a/tests/hardhat/JumpRateModelV2.ts +++ b/tests/hardhat/JumpRateModelV2.ts @@ -4,7 +4,7 @@ import BigNumber from "bignumber.js"; import chai from "chai"; import { ethers } from "hardhat"; -import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; +import { BSC_BLOCKS_PER_YEAR } from "../../helpers/deploymentConfig"; import { convertToUnit } from "../../helpers/utils"; import { AccessControlManager, JumpRateModelV2 } from "../../typechain"; import { getDescription } from "./util/descriptionHelpers"; @@ -49,7 +49,7 @@ for (const isTimeBased of [false, true]) { before(async () => { await loadFixture(fixture); - slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; + slotsPerYear = (await jumpRateModel.blocksOrSecondsPerYear()).toNumber(); }); it("Update jump rate model", async () => { diff --git a/tests/hardhat/WhitePaperInterestRateModel.ts b/tests/hardhat/WhitePaperInterestRateModel.ts index f2d83ddf6..73333763e 100644 --- a/tests/hardhat/WhitePaperInterestRateModel.ts +++ b/tests/hardhat/WhitePaperInterestRateModel.ts @@ -4,7 +4,7 @@ import BigNumber from "bignumber.js"; import chai from "chai"; import { ethers } from "hardhat"; -import { BSC_BLOCKS_PER_YEAR, SECONDS_PER_YEAR } from "../../helpers/deploymentConfig"; +import { BSC_BLOCKS_PER_YEAR } from "../../helpers/deploymentConfig"; import { convertToUnit } from "../../helpers/utils"; import { WhitePaperInterestRateModel } from "../../typechain"; import { getDescription } from "./util/descriptionHelpers"; @@ -38,7 +38,7 @@ for (const isTimeBased of [false, true]) { before(async () => { await loadFixture(fixture); - slotsPerYear = isTimeBased ? SECONDS_PER_YEAR : BSC_BLOCKS_PER_YEAR; + slotsPerYear = (await interestRateModel.blocksOrSecondsPerYear()).toNumber(); }); it("Model getters", async () => { diff --git a/tests/hardhat/util/TokenTestHelpers.ts b/tests/hardhat/util/TokenTestHelpers.ts index 0263ac44b..505834327 100644 --- a/tests/hardhat/util/TokenTestHelpers.ts +++ b/tests/hardhat/util/TokenTestHelpers.ts @@ -111,10 +111,10 @@ const deployVTokenDependencies = async ( { kind }, params.isTimeBased || false, - params.blocksPerYear === 0 ? 0 : BSC_BLOCKS_PER_YEAR, + params.blocksPerYear === undefined ? BSC_BLOCKS_PER_YEAR : params.blocksPerYear, )), isTimeBased: params.isTimeBased || false, - blocksPerYear: params.blocksPerYear === 0 ? 0 : BSC_BLOCKS_PER_YEAR, + blocksPerYear: params.blocksPerYear === undefined ? BSC_BLOCKS_PER_YEAR : params.blocksPerYear, }; }; From e1cdb75c1b3f9f9eaca720885704f75052eb69e3 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 10 Jan 2024 14:51:51 +0530 Subject: [PATCH 05/22] fix: SSV-01 --- contracts/Shortfall/Shortfall.sol | 47 +++++++++++++++------------- deploy/014-riskfund-protocolshare.ts | 4 ++- package.json | 2 +- tests/hardhat/Fork/RiskFundSwap.ts | 2 +- tests/hardhat/Shortfall.ts | 9 ++++-- yarn.lock | 10 +++--- 6 files changed, 42 insertions(+), 32 deletions(-) diff --git a/contracts/Shortfall/Shortfall.sol b/contracts/Shortfall/Shortfall.sol index 0d5c96b39..3ba28f802 100644 --- a/contracts/Shortfall/Shortfall.sol +++ b/contracts/Shortfall/Shortfall.sol @@ -7,14 +7,15 @@ import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol"; -import { VToken } from "../VToken.sol"; +import { ensureNonzeroAddress, ensureNonzeroValue } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; + +import { VToken } from "../VToken.sol"; import { ComptrollerInterface, ComptrollerViewInterface } from "../ComptrollerInterface.sol"; import { IRiskFund } from "../RiskFund/IRiskFund.sol"; import { PoolRegistry } from "../Pool/PoolRegistry.sol"; import { PoolRegistryInterface } from "../Pool/PoolRegistryInterface.sol"; import { TokenDebtTracker } from "../lib/TokenDebtTracker.sol"; -import { ensureNonzeroAddress } from "../lib/validators.sol"; import { EXP_SCALE } from "../lib/constants.sol"; /** @@ -69,21 +70,17 @@ contract Shortfall is /// @dev Max basis points i.e., 100% uint256 private constant MAX_BPS = 10000; - // @notice Default block limit for the next bidder to place a bid - uint256 private constant DEFAULT_NEXT_BIDDER_BLOCK_LIMIT = 100; - - // @notice Default number of blocks to wait for the first bidder before starting the auction - uint256 private constant DEFAULT_WAIT_FOR_FIRST_BIDDER = 100; - - // @notice Default block timestamp limit for the next bidder to place a bid - uint256 private constant DEFAULT_NEXT_BIDDER_BLOCK_TIMESTAMP_LIMIT = 300; - - // @notice Default time limit in seconds for the first bidder to place a bid before the auction starts - uint256 private constant DEFAULT_WAIT_FOR_FIRST_BIDDER_IN_SECONDS = 300; - // @notice Default incentive basis points (BPS) for the auction participants, set to 10% uint256 private constant DEFAULT_INCENTIVE_BPS = 1000; + // @notice Default block or timestamp limit for the next bidder to place a bid + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + uint256 private immutable DEFAULT_NEXT_BIDDER_BLOCK_OR_TIMESTAMP_LIMIT; + + // @notice Default number of blocks or seconds to wait for the first bidder before starting the auction + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + uint256 private immutable DEFAULT_WAIT_FOR_FIRST_BIDDER; + /// @notice Pool registry address address public poolRegistry; @@ -170,7 +167,18 @@ contract Shortfall is * @param blocksPerYear_ The number of blocks per year * @custom:oz-upgrades-unsafe-allow constructor */ - constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) { + constructor( + bool timeBased_, + uint256 blocksPerYear_, + uint256 nextBidderBlockOrTimestampLimit_, + uint256 waitForFirstBidder_ + ) TimeManagerV8(timeBased_, blocksPerYear_) { + ensureNonzeroValue(nextBidderBlockOrTimestampLimit_); + ensureNonzeroValue(waitForFirstBidder_); + + DEFAULT_NEXT_BIDDER_BLOCK_OR_TIMESTAMP_LIMIT = nextBidderBlockOrTimestampLimit_; + DEFAULT_WAIT_FOR_FIRST_BIDDER = waitForFirstBidder_; + // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. _disableInitializers(); @@ -201,13 +209,8 @@ contract Shortfall is incentiveBps = DEFAULT_INCENTIVE_BPS; auctionsPaused = false; - if (isTimeBased) { - waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER_IN_SECONDS; - nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_TIMESTAMP_LIMIT; - } else { - waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER; - nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_LIMIT; - } + waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER; + nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_OR_TIMESTAMP_LIMIT; } /** diff --git a/deploy/014-riskfund-protocolshare.ts b/deploy/014-riskfund-protocolshare.ts index 49d75280c..08c8e93ae 100644 --- a/deploy/014-riskfund-protocolshare.ts +++ b/deploy/014-riskfund-protocolshare.ts @@ -11,6 +11,8 @@ import { Comptroller } from "../typechain"; const MIN_AMOUNT_TO_CONVERT = convertToUnit(10, 18); const MIN_POOL_BAD_DEBT = convertToUnit(1000, 18); const maxLoopsLimit = 100; +const waitForFirstBidder = 100; // for block based contracts deployment +const nextBidderBlockOrTimestampLimit = 100; // for block based contracts deployment const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; @@ -71,7 +73,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }, upgradeIndex: 0, }, - args: [isTimeBased, blocksPerYear], + args: [isTimeBased, blocksPerYear, nextBidderBlockOrTimestampLimit, waitForFirstBidder], autoMine: true, log: true, }); diff --git a/package.json b/package.json index 641e329d6..8b9cac8ed 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "@openzeppelin/contracts-upgradeable": "^4.8.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", "@solidity-parser/parser": "^0.13.2", - "@venusprotocol/solidity-utilities": "^1.2.0-dev.1", + "@venusprotocol/solidity-utilities": "^1.3.0", "ethers": "^5.7.0", "hardhat-deploy": "^0.11.14", "module-alias": "^2.2.2" diff --git a/tests/hardhat/Fork/RiskFundSwap.ts b/tests/hardhat/Fork/RiskFundSwap.ts index b1887186d..30dc93a5f 100644 --- a/tests/hardhat/Fork/RiskFundSwap.ts +++ b/tests/hardhat/Fork/RiskFundSwap.ts @@ -108,7 +108,7 @@ const riskFundFixture = async (): Promise => { const shortfall = await upgrades.deployProxy( Shortfall, [AddressOne, parseUnits("10000", 18), fakeAccessControlManager.address], - { constructorArgs: [false, 10512000] }, + { constructorArgs: [false, 10512000, 100, 100] }, ); const fakeCorePoolComptroller = await smock.fake("Comptroller"); diff --git a/tests/hardhat/Shortfall.ts b/tests/hardhat/Shortfall.ts index 3653f28e7..2aabd592d 100644 --- a/tests/hardhat/Shortfall.ts +++ b/tests/hardhat/Shortfall.ts @@ -50,6 +50,8 @@ const riskFundBalance = "10000"; const minimumPoolBadDebt = "10000"; let isTimeBased = false; // for block based contracts let blocksPerYear = BSC_BLOCKS_PER_YEAR; // for block based contracts +let waitForFirstBidder = 100; // for block based contracts +let nextBidderBlockOrTimestampLimit = 100; // for block based contracts let poolAddress; /** @@ -68,7 +70,7 @@ async function shortfallFixture() { shortfall = await upgrades.deployProxy( Shortfall, [fakeRiskFund.address, parseUnits(minimumPoolBadDebt, "18"), accessControlManager.address], - { constructorArgs: [isTimeBased, blocksPerYear] }, + { constructorArgs: [isTimeBased, blocksPerYear, nextBidderBlockOrTimestampLimit, waitForFirstBidder] }, ); [owner, someone, bidder1, bidder2] = await ethers.getSigners(); @@ -184,6 +186,9 @@ async function shortfallFixture() { async function timeBasedhortfallFixture() { isTimeBased = true; blocksPerYear = 0; + waitForFirstBidder = 300; + nextBidderBlockOrTimestampLimit = 300; + const MockBUSD = await ethers.getContractFactory("MockToken"); mockBUSD = await MockBUSD.deploy("BUSD", "BUSD", 18); await mockBUSD.faucet(convertToUnit(100000, 18)); @@ -197,7 +202,7 @@ async function timeBasedhortfallFixture() { Shortfall, [fakeRiskFund.address, parseUnits(minimumPoolBadDebt, "18"), accessControlManager.address], { - constructorArgs: [isTimeBased, blocksPerYear], + constructorArgs: [isTimeBased, blocksPerYear, nextBidderBlockOrTimestampLimit, waitForFirstBidder], }, ); [owner, someone, bidder1, bidder2] = await ethers.getSigners(); diff --git a/yarn.lock b/yarn.lock index b9dde95a7..a8a6bb81d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2985,7 +2985,7 @@ __metadata: "@venusprotocol/governance-contracts": 1.4.0-dev.2 "@venusprotocol/oracle": 1.8.0-dev.3 "@venusprotocol/protocol-reserve": 1.2.0-dev.2 - "@venusprotocol/solidity-utilities": ^1.2.0-dev.1 + "@venusprotocol/solidity-utilities": ^1.3.0 "@venusprotocol/venus-protocol": 6.0.1-dev.2 bignumber.js: 9.0.0 chai: ^4.3.6 @@ -3060,10 +3060,10 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/solidity-utilities@npm:^1.2.0-dev.1": - version: 1.2.0-dev.1 - resolution: "@venusprotocol/solidity-utilities@npm:1.2.0-dev.1" - checksum: 0e7958c4dea51cc2d84cdc9039d21e00d265863573fb0d1eab575bd2f9d5b50c80dce60f96213a7d9764f9f7c8a03403e89c838cd3539c75632e66e1f59dcdec +"@venusprotocol/solidity-utilities@npm:^1.3.0": + version: 1.3.0 + resolution: "@venusprotocol/solidity-utilities@npm:1.3.0" + checksum: d1109365a5e01959c47b25fb129373db93792e60bf1bc0ed324b63c2a64f6e4a7878ebf016cfade94bc41a2c1245d3e861fdc6b8c5844ac210ed1d73e7307e72 languageName: node linkType: hard From 88265c396aaac27b24499a9c340dc2022aa762b5 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 10 Jan 2024 17:18:10 +0530 Subject: [PATCH 06/22] fix: VPB-01 value naming should be updated to reflect possible time-based case --- contracts/Comptroller.sol | 2 +- contracts/InterestRateModel.sol | 8 +++--- contracts/Lens/PoolLens.sol | 16 +++++------ contracts/Rewards/RewardsDistributor.sol | 36 ++++++++++++------------ contracts/Shortfall/Shortfall.sol | 36 ++++++++++++------------ contracts/VTokenInterfaces.sol | 13 +++++---- 6 files changed, 57 insertions(+), 54 deletions(-) diff --git a/contracts/Comptroller.sol b/contracts/Comptroller.sol index 1b9ecd6c2..fdaaa0c18 100644 --- a/contracts/Comptroller.sol +++ b/contracts/Comptroller.sol @@ -1061,7 +1061,7 @@ contract Comptroller is /** * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor - * contracts with the same rewardToken, and there could be overlaping among them considering the last reward block + * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second) * @dev Only callable by the admin * @param _rewardsDistributor Address of the RewardDistributor contract to add * @custom:access Only Governance diff --git a/contracts/InterestRateModel.sol b/contracts/InterestRateModel.sol index 354b8f1e7..8a63446ab 100644 --- a/contracts/InterestRateModel.sol +++ b/contracts/InterestRateModel.sol @@ -7,12 +7,12 @@ pragma solidity 0.8.13; */ abstract contract InterestRateModel { /** - * @notice Calculates the current borrow interest rate per block + * @notice Calculates the current borrow interest rate per slot (block or second) * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @param badDebt The amount of badDebt in the market - * @return The borrow rate per block (as a percentage, and scaled by 1e18) + * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE) */ function getBorrowRate( uint256 cash, @@ -22,13 +22,13 @@ abstract contract InterestRateModel { ) external view virtual returns (uint256); /** - * @notice Calculates the current supply interest rate per block + * @notice Calculates the current supply interest rate per slot (block or second) * @param cash The total amount of cash the market has * @param borrows The total amount of borrows the market has outstanding * @param reserves The total amount of reserves the market has * @param reserveFactorMantissa The current reserve factor the market has * @param badDebt The amount of badDebt in the market - * @return The supply rate per block (as a percentage, and scaled by 1e18) + * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE) */ function getSupplyRate( uint256 cash, diff --git a/contracts/Lens/PoolLens.sol b/contracts/Lens/PoolLens.sol index 81a6cfff3..b42aa4544 100644 --- a/contracts/Lens/PoolLens.sol +++ b/contracts/Lens/PoolLens.sol @@ -504,16 +504,16 @@ contract PoolLens is TimeManagerV8, ExponentialNoError { blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp; } - uint256 deltaBlocks = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp); - if (deltaBlocks > 0 && borrowSpeed > 0) { + uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp); + if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) { // Remove the total earned interest rate since the opening of the market from total borrows uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex); - uint256 tokensAccrued = mul_(deltaBlocks, borrowSpeed); + uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed); Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, borrowAmount) : Double({ mantissa: 0 }); Double memory index = add_(Double({ mantissa: borrowState.index }), ratio); borrowState.index = safe224(index.mantissa, "new index overflows"); borrowState.blockOrTimestamp = blockNumberOrTimestamp; - } else if (deltaBlocks > 0) { + } else if (deltaBlocksOrTimestamp > 0) { borrowState.blockOrTimestamp = blockNumberOrTimestamp; } } @@ -533,15 +533,15 @@ contract PoolLens is TimeManagerV8, ExponentialNoError { blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp; } - uint256 deltaBlocks = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp); - if (deltaBlocks > 0 && supplySpeed > 0) { + uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp); + if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) { uint256 supplyTokens = VToken(vToken).totalSupply(); - uint256 tokensAccrued = mul_(deltaBlocks, supplySpeed); + uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed); Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, supplyTokens) : Double({ mantissa: 0 }); Double memory index = add_(Double({ mantissa: supplyState.index }), ratio); supplyState.index = safe224(index.mantissa, "new index overflows"); supplyState.blockOrTimestamp = blockNumberOrTimestamp; - } else if (deltaBlocks > 0) { + } else if (deltaBlocksOrTimestamp > 0) { supplyState.blockOrTimestamp = blockNumberOrTimestamp; } } diff --git a/contracts/Rewards/RewardsDistributor.sol b/contracts/Rewards/RewardsDistributor.sol index 938ca8769..261c4796f 100644 --- a/contracts/Rewards/RewardsDistributor.sol +++ b/contracts/Rewards/RewardsDistributor.sol @@ -19,9 +19,9 @@ import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeM * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool. * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward - * token to be released each block for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies + * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting - * their contributor reward token speed, which similarly allocates a fixed amount of reward token per block. + * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second). * * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized @@ -66,19 +66,19 @@ contract RewardsDistributor is /// @notice The REWARD TOKEN accrued but not yet transferred to each user mapping(address => uint256) public rewardTokenAccrued; - /// @notice The rate at which rewardToken is distributed to the corresponding borrow market (per block) + /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second) mapping(address => uint256) public rewardTokenBorrowSpeeds; - /// @notice The rate at which rewardToken is distributed to the corresponding supply market (per block) + /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second) mapping(address => uint256) public rewardTokenSupplySpeeds; /// @notice The REWARD TOKEN market borrow state for each market mapping(address => RewardToken) public rewardTokenBorrowState; - /// @notice The portion of REWARD TOKEN that each contributor receives per block + /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second) mapping(address => uint256) public rewardTokenContributorSpeeds; - /// @notice Last block at which a contributor's REWARD TOKEN rewards have been allocated + /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated mapping(address => uint256) public lastContributorBlock; /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN @@ -136,17 +136,17 @@ contract RewardsDistributor is /// @notice Emitted when a reward for contributor is updated event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued); - /// @notice Emitted when a reward token last rewarding block for supply is updated - event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock); + /// @notice Emitted when a reward token last rewarding slot (block or second) for supply is updated + event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlockNumberOrTimestamp); - /// @notice Emitted when a reward token last rewarding block for borrow is updated - event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock); + /// @notice Emitted when a reward token last rewarding slot (block or second) for borrow is updated + event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlockNumberOrTimestamp); - /// @notice Emitted when a reward token last rewarding block timestamp for supply is updated - event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newBlock); + /// @notice Emitted when a reward token last rewarding slot (block or second) for supply is updated + event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newBlockNumberOrTimestamp); - /// @notice Emitted when a reward token last rewarding block timestamp for borrow is updated - event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newBlock); + /// @notice Emitted when a reward token last rewarding slot (block or second) for borrow is updated + event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newBlockNumberOrTimestamp); modifier onlyComptroller() { require(address(comptroller) == msg.sender, "Only comptroller can call this function"); @@ -445,10 +445,10 @@ contract RewardsDistributor is } /** - * @notice Set REWARD TOKEN last rewarding block for a single market. - * @param vToken market's whose reward token last rewarding block to be updated - * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding block for market - * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding block for market + * @notice Set REWARD TOKEN last rewarding slot (block or second) for a single market. + * @param vToken market's whose reward token last rewarding slot (block or second) to be updated + * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding slot (block or second) for market + * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding slot (block or second) for market */ function _setLastRewardingBlockTimestamp( VToken vToken, diff --git a/contracts/Shortfall/Shortfall.sol b/contracts/Shortfall/Shortfall.sol index 3ba28f802..c8efc1075 100644 --- a/contracts/Shortfall/Shortfall.sol +++ b/contracts/Shortfall/Shortfall.sol @@ -353,56 +353,56 @@ contract Shortfall is /** * @notice Update next bidder block or timestamp limit which is used determine when an auction can be closed - * @param _nextBidderBlockOrTimestampLimit New next bidder block limit + * @param nextBidderBlockOrTimestampLimit_ New next bidder slot (block or second) limit * @custom:event Emits NextBidderBlockLimitUpdated on success * @custom:access Restricted by ACM */ - function updateNextBidderBlockLimit(uint256 _nextBidderBlockOrTimestampLimit) external { + function updateNextBidderBlockLimit(uint256 nextBidderBlockOrTimestampLimit_) external { _checkAccessAllowed("updateNextBidderBlockLimit(uint256)"); - require(_nextBidderBlockOrTimestampLimit != 0, "_nextBidderBlockOrTimestampLimit must not be 0"); + require(nextBidderBlockOrTimestampLimit_ != 0, "nextBidderBlockOrTimestampLimit_ must not be 0"); - emit NextBidderBlockLimitUpdated(nextBidderBlockLimit, _nextBidderBlockOrTimestampLimit); - nextBidderBlockLimit = _nextBidderBlockOrTimestampLimit; + emit NextBidderBlockLimitUpdated(nextBidderBlockLimit, nextBidderBlockOrTimestampLimit_); + nextBidderBlockLimit = nextBidderBlockOrTimestampLimit_; } /** * @notice Updates the incentive BPS - * @param _incentiveBps New incentive BPS + * @param incentiveBps_ New incentive BPS * @custom:event Emits IncentiveBpsUpdated on success * @custom:access Restricted by ACM */ - function updateIncentiveBps(uint256 _incentiveBps) external { + function updateIncentiveBps(uint256 incentiveBps_) external { _checkAccessAllowed("updateIncentiveBps(uint256)"); - require(_incentiveBps != 0, "incentiveBps must not be 0"); + require(incentiveBps_ != 0, "incentiveBps must not be 0"); uint256 oldIncentiveBps = incentiveBps; - incentiveBps = _incentiveBps; - emit IncentiveBpsUpdated(oldIncentiveBps, _incentiveBps); + incentiveBps = incentiveBps_; + emit IncentiveBpsUpdated(oldIncentiveBps, incentiveBps_); } /** * @notice Update minimum pool bad debt to start auction - * @param _minimumPoolBadDebt Minimum bad debt in the base asset for a pool to start auction + * @param minimumPoolBadDebt_ Minimum bad debt in the base asset for a pool to start auction * @custom:event Emits MinimumPoolBadDebtUpdated on success * @custom:access Restricted by ACM */ - function updateMinimumPoolBadDebt(uint256 _minimumPoolBadDebt) external { + function updateMinimumPoolBadDebt(uint256 minimumPoolBadDebt_) external { _checkAccessAllowed("updateMinimumPoolBadDebt(uint256)"); uint256 oldMinimumPoolBadDebt = minimumPoolBadDebt; - minimumPoolBadDebt = _minimumPoolBadDebt; - emit MinimumPoolBadDebtUpdated(oldMinimumPoolBadDebt, _minimumPoolBadDebt); + minimumPoolBadDebt = minimumPoolBadDebt_; + emit MinimumPoolBadDebtUpdated(oldMinimumPoolBadDebt, minimumPoolBadDebt_); } /** * @notice Update wait for first bidder block or timestamp count. If the first bid is not made within this limit, the auction is closed and needs to be restarted - * @param _waitForFirstBidder New wait for first bidder block or timestamp count + * @param waitForFirstBidder_ New wait for first bidder block or timestamp count * @custom:event Emits WaitForFirstBidderUpdated on success * @custom:access Restricted by ACM */ - function updateWaitForFirstBidder(uint256 _waitForFirstBidder) external { + function updateWaitForFirstBidder(uint256 waitForFirstBidder_) external { _checkAccessAllowed("updateWaitForFirstBidder(uint256)"); uint256 oldWaitForFirstBidder = waitForFirstBidder; - waitForFirstBidder = _waitForFirstBidder; - emit WaitForFirstBidderUpdated(oldWaitForFirstBidder, _waitForFirstBidder); + waitForFirstBidder = waitForFirstBidder_; + emit WaitForFirstBidderUpdated(oldWaitForFirstBidder, waitForFirstBidder_); } /** diff --git a/contracts/VTokenInterfaces.sol b/contracts/VTokenInterfaces.sol index 172ac5ee6..3901cf1db 100644 --- a/contracts/VTokenInterfaces.sol +++ b/contracts/VTokenInterfaces.sol @@ -54,7 +54,7 @@ contract VTokenStorage { */ address payable public protocolShareReserve; - // Maximum borrow rate that can ever be applied (.0005% / block) + // Maximum borrow rate that can ever be applied (.0005% / slot(block or second)) uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16; // Maximum fraction of interest that can be set aside for reserves @@ -128,12 +128,12 @@ contract VTokenStorage { address public shortfall; /** - * @notice delta block after which reserves will be reduced + * @notice delta slot (block or second) after which reserves will be reduced */ uint256 public reduceReservesBlockDelta; /** - * @notice last block number at which reserves were reduced + * @notice last slot (block or second) number at which reserves were reduced */ uint256 public reduceReservesBlockNumber; @@ -282,9 +282,12 @@ abstract contract VTokenInterface is VTokenStorage { event SweepToken(address indexed token); /** - * @notice Event emitted when reduce reserves block delta is changed + * @notice Event emitted when reduce reserves slot (block or second) delta is changed */ - event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta); + event NewReduceReservesBlockDelta( + uint256 oldReduceReservesBlockOrTimestampDelta, + uint256 newReduceReservesBlockOrTimestampDelta + ); /** * @notice Event emitted when liquidation reserves are reduced From ee4c083f24fe91bacbf4da10f2412dbeac476a53 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 10 Jan 2024 18:14:37 +0530 Subject: [PATCH 07/22] fix: VPB-03 maximum should depend on chain and whether the contracts are time or block-based --- contracts/VToken.sol | 14 +++++++++++++- contracts/VTokenInterfaces.sol | 6 ------ contracts/test/UpgradedVToken.sol | 6 +++++- contracts/test/VTokenHarness.sol | 8 ++++++-- deploy/009-deploy-vtokens.ts | 3 ++- deploy/016-deploy-beacon-implementations.ts | 3 ++- tests/hardhat/Rewards.ts | 4 +++- tests/hardhat/Shortfall.ts | 16 ++++++++++------ tests/hardhat/UpgradedVToken.ts | 4 +++- tests/hardhat/util/TokenTestHelpers.ts | 6 +++++- 10 files changed, 49 insertions(+), 21 deletions(-) diff --git a/contracts/VToken.sol b/contracts/VToken.sol index cd2129ce9..28e10e30a 100644 --- a/contracts/VToken.sol +++ b/contracts/VToken.sol @@ -53,6 +53,13 @@ contract VToken is uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5% + // Maximum fraction of interest that can be set aside for reserves + uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18; + + // Maximum borrow rate that can ever be applied (.0005% / slot(block or second)) + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + uint256 internal immutable MAX_BORROW_RATE_MANTISSA; + /** * Reentrancy Guard ** */ @@ -72,9 +79,14 @@ contract VToken is * @param blocksPerYear_ The number of blocks per year * @custom:oz-upgrades-unsafe-allow constructor */ - constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) { + constructor( + bool timeBased_, + uint256 blocksPerYear_, + uint256 maxBorrowRateMantissa_ + ) TimeManagerV8(timeBased_, blocksPerYear_) { // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. + MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_; _disableInitializers(); } diff --git a/contracts/VTokenInterfaces.sol b/contracts/VTokenInterfaces.sol index 3901cf1db..e3e2d1304 100644 --- a/contracts/VTokenInterfaces.sol +++ b/contracts/VTokenInterfaces.sol @@ -54,12 +54,6 @@ contract VTokenStorage { */ address payable public protocolShareReserve; - // Maximum borrow rate that can ever be applied (.0005% / slot(block or second)) - uint256 internal constant MAX_BORROW_RATE_MANTISSA = 0.0005e16; - - // Maximum fraction of interest that can be set aside for reserves - uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18; - /** * @notice Contract which oversees inter-vToken operations */ diff --git a/contracts/test/UpgradedVToken.sol b/contracts/test/UpgradedVToken.sol index 1739641d3..efae5ac4f 100644 --- a/contracts/test/UpgradedVToken.sol +++ b/contracts/test/UpgradedVToken.sol @@ -18,7 +18,11 @@ contract UpgradedVToken is VToken { * @param blocksPerYear_ The number of blocks per year * @custom:oz-upgrades-unsafe-allow constructor */ - constructor(bool timeBased_, uint256 blocksPerYear_) VToken(timeBased_, blocksPerYear_) { + constructor( + bool timeBased_, + uint256 blocksPerYear_, + uint256 maxBorrowRateMantissa_ + ) VToken(timeBased_, blocksPerYear_, maxBorrowRateMantissa_) { // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. _disableInitializers(); diff --git a/contracts/test/VTokenHarness.sol b/contracts/test/VTokenHarness.sol index a1a4045a3..36a9ab7fc 100644 --- a/contracts/test/VTokenHarness.sol +++ b/contracts/test/VTokenHarness.sol @@ -18,7 +18,11 @@ contract VTokenHarness is VToken { * @param blocksPerYear_ The number of blocks per year * @custom:oz-upgrades-unsafe-allow constructor */ - constructor(bool timeBased_, uint256 blocksPerYear_) VToken(timeBased_, blocksPerYear_) { + constructor( + bool timeBased_, + uint256 blocksPerYear_, + uint256 maxBorrowRateMantissa_ + ) VToken(timeBased_, blocksPerYear_, maxBorrowRateMantissa_) { // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. _disableInitializers(); @@ -118,7 +122,7 @@ contract VTokenHarness is VToken { return (snapshot.principal, snapshot.interestIndex); } - function getBorrowRateMaxMantissa() external pure returns (uint256) { + function getBorrowRateMaxMantissa() external view returns (uint256) { return MAX_BORROW_RATE_MANTISSA; } diff --git a/deploy/009-deploy-vtokens.ts b/deploy/009-deploy-vtokens.ts index 9a90a76ab..f5201c8b0 100644 --- a/deploy/009-deploy-vtokens.ts +++ b/deploy/009-deploy-vtokens.ts @@ -21,6 +21,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { tokensConfig, poolConfig, preconfiguredAddresses } = await getConfig(hre.network.name); const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.network.name); + const maxBorrowRateMantissa = BigNumber.from(0.0005e16); const accessControlManagerAddress = await toAddress( preconfiguredAddresses.AccessControlManager || "AccessControlManager", @@ -31,7 +32,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const vTokenImpl: DeployResult = await deploy("VTokenImpl", { contract: "VToken", from: deployer, - args: [isTimeBased, blocksPerYear], + args: [isTimeBased, blocksPerYear, maxBorrowRateMantissa], log: true, autoMine: true, }); diff --git a/deploy/016-deploy-beacon-implementations.ts b/deploy/016-deploy-beacon-implementations.ts index 99e267481..2fb722921 100644 --- a/deploy/016-deploy-beacon-implementations.ts +++ b/deploy/016-deploy-beacon-implementations.ts @@ -13,6 +13,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.network.name); const poolRegistry = await ethers.getContract("PoolRegistry"); + const maxBorrowRateMantissa = ethers.BigNumber.from(0.0005e16); // Comptroller Implementation await deploy("ComptrollerImpl", { @@ -27,7 +28,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { await deploy("VTokenImpl", { contract: "VToken", from: deployer, - args: [isTimeBased, blocksPerYear], + args: [isTimeBased, blocksPerYear, maxBorrowRateMantissa], log: true, autoMine: true, }); diff --git a/tests/hardhat/Rewards.ts b/tests/hardhat/Rewards.ts index bc442d4c3..0a36265c7 100644 --- a/tests/hardhat/Rewards.ts +++ b/tests/hardhat/Rewards.ts @@ -63,6 +63,8 @@ async function rewardsFixture(isTimeBased: boolean) { const btcPrice = "21000.34"; const daiPrice = "1"; + const maxBorrowRateMantissa = ethers.BigNumber.from(0.0005e16); + fakePriceOracle.getUnderlyingPrice.returns((args: any) => { if (vDAI && vWBTC) { if (args[0] === vDAI.address) { @@ -104,7 +106,7 @@ async function rewardsFixture(isTimeBased: boolean) { // Deploy VTokens const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor"); - const vTokenBeacon = await deployVTokenBeacon(undefined, isTimeBased, blocksPerYear); + const vTokenBeacon = await deployVTokenBeacon(undefined, maxBorrowRateMantissa, isTimeBased, blocksPerYear); vWBTC = await makeVToken({ underlying: mockWBTC, comptroller: comptrollerProxy, diff --git a/tests/hardhat/Shortfall.ts b/tests/hardhat/Shortfall.ts index 2aabd592d..c9b48c3c8 100644 --- a/tests/hardhat/Shortfall.ts +++ b/tests/hardhat/Shortfall.ts @@ -62,6 +62,8 @@ async function shortfallFixture() { mockBUSD = await MockBUSD.deploy("BUSD", "BUSD", 18); await mockBUSD.faucet(convertToUnit(100000, 18)); + const maxBorrowRateMantissa = ethers.BigNumber.from(0.0005e16); + const AccessControlManagerFactor = await ethers.getContractFactory("AccessControlManager"); accessControlManager = await AccessControlManagerFactor.deploy(); fakeRiskFund = await smock.fake("IRiskFund"); @@ -104,9 +106,9 @@ async function shortfallFixture() { }); const VToken = await smock.mock("VToken"); - vDAI = await VToken.deploy(isTimeBased, blocksPerYear); - vWBTC = await VToken.deploy(isTimeBased, blocksPerYear); - vFloki = await VToken.deploy(isTimeBased, blocksPerYear); + vDAI = await VToken.deploy(isTimeBased, blocksPerYear, maxBorrowRateMantissa); + vWBTC = await VToken.deploy(isTimeBased, blocksPerYear, maxBorrowRateMantissa); + vFloki = await VToken.deploy(isTimeBased, blocksPerYear, maxBorrowRateMantissa); await vWBTC.setVariable("decimals", 8); vDAI.decimals.returns(18); @@ -189,6 +191,8 @@ async function timeBasedhortfallFixture() { waitForFirstBidder = 300; nextBidderBlockOrTimestampLimit = 300; + const maxBorrowRateMantissa = ethers.BigNumber.from(0.0005e16); + const MockBUSD = await ethers.getContractFactory("MockToken"); mockBUSD = await MockBUSD.deploy("BUSD", "BUSD", 18); await mockBUSD.faucet(convertToUnit(100000, 18)); @@ -236,9 +240,9 @@ async function timeBasedhortfallFixture() { }); const VToken = await smock.mock("VToken"); - vDAI = await VToken.deploy(isTimeBased, blocksPerYear); - vWBTC = await VToken.deploy(isTimeBased, blocksPerYear); - vFloki = await VToken.deploy(isTimeBased, blocksPerYear); + vDAI = await VToken.deploy(isTimeBased, blocksPerYear, maxBorrowRateMantissa); + vWBTC = await VToken.deploy(isTimeBased, blocksPerYear, maxBorrowRateMantissa); + vFloki = await VToken.deploy(isTimeBased, blocksPerYear, maxBorrowRateMantissa); await vWBTC.setVariable("decimals", 8); vDAI.decimals.returns(18); diff --git a/tests/hardhat/UpgradedVToken.ts b/tests/hardhat/UpgradedVToken.ts index 6920741e5..5855a2952 100644 --- a/tests/hardhat/UpgradedVToken.ts +++ b/tests/hardhat/UpgradedVToken.ts @@ -106,8 +106,10 @@ for (const isTimeBased of [false, true]) { }); it("Upgrade the vToken contract", async function () { + const maxBorrowRateMantissa = ethers.BigNumber.from(0.0005e16); + const vToken = await ethers.getContractFactory("UpgradedVToken"); - const vTokenDeploy = await vToken.deploy(isTimeBased, slotsPerYear); + const vTokenDeploy = await vToken.deploy(isTimeBased, slotsPerYear, maxBorrowRateMantissa); await vTokenDeploy.deployed(); diff --git a/tests/hardhat/util/TokenTestHelpers.ts b/tests/hardhat/util/TokenTestHelpers.ts index 505834327..e7e86b5fa 100644 --- a/tests/hardhat/util/TokenTestHelpers.ts +++ b/tests/hardhat/util/TokenTestHelpers.ts @@ -37,6 +37,7 @@ interface VTokenParameters { beacon: UpgradeableBeacon; isTimeBased: boolean; blocksPerYear: BigNumberish; + maxBorrowRateMantissa: BigNumberish; } const getNameAndSymbol = async (underlying: AddressOrContract): Promise<[string, string]> => { @@ -74,12 +75,13 @@ export type AnyVTokenFactory = VTokenHarness__factory | VToken__factory; export const deployVTokenBeacon = async ( { kind }: { kind: string } = { kind: "VToken" }, + maxBorrowRateMantissa: BigNumberish = BigNumber.from(0.0005e16), isTimeBased: boolean = false, blocksPerYear: BigNumberish = BSC_BLOCKS_PER_YEAR, ): Promise => { const VToken = await ethers.getContractFactory(kind); const vTokenBeacon = (await upgrades.deployBeacon(VToken, { - constructorArgs: [isTimeBased, blocksPerYear], + constructorArgs: [isTimeBased, blocksPerYear, maxBorrowRateMantissa], })) as UpgradeableBeacon; return vTokenBeacon; }; @@ -106,10 +108,12 @@ const deployVTokenDependencies = async ( { kind }, + params.maxBorrowRateMantissa || BigNumber.from(0.0005e16), params.isTimeBased || false, params.blocksPerYear === undefined ? BSC_BLOCKS_PER_YEAR : params.blocksPerYear, )), From 25ed2b1ef2fc35b7f24628fdabadcd43d7037648 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 11 Jan 2024 13:12:12 +0530 Subject: [PATCH 08/22] fixup: VPB-01 value naming should be updated to reflect possible time-based case --- contracts/Rewards/RewardsDistributor.sol | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/contracts/Rewards/RewardsDistributor.sol b/contracts/Rewards/RewardsDistributor.sol index 261c4796f..273c4e3d5 100644 --- a/contracts/Rewards/RewardsDistributor.sol +++ b/contracts/Rewards/RewardsDistributor.sol @@ -136,17 +136,17 @@ contract RewardsDistributor is /// @notice Emitted when a reward for contributor is updated event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued); - /// @notice Emitted when a reward token last rewarding slot (block or second) for supply is updated - event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlockNumberOrTimestamp); + /// @notice Emitted when a reward token last rewarding block for supply is updated + event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock); - /// @notice Emitted when a reward token last rewarding slot (block or second) for borrow is updated - event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlockNumberOrTimestamp); + /// @notice Emitted when a reward token last rewarding block for borrow is updated + event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock); - /// @notice Emitted when a reward token last rewarding slot (block or second) for supply is updated - event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newBlockNumberOrTimestamp); + /// @notice Emitted when a reward token last rewarding timestamp for supply is updated + event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp); - /// @notice Emitted when a reward token last rewarding slot (block or second) for borrow is updated - event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newBlockNumberOrTimestamp); + /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated + event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp); modifier onlyComptroller() { require(address(comptroller) == msg.sender, "Only comptroller can call this function"); @@ -445,10 +445,10 @@ contract RewardsDistributor is } /** - * @notice Set REWARD TOKEN last rewarding slot (block or second) for a single market. - * @param vToken market's whose reward token last rewarding slot (block or second) to be updated - * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding slot (block or second) for market - * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding slot (block or second) for market + * @notice Set REWARD TOKEN last rewarding timestamp for a single market. + * @param vToken market's whose reward token last rewarding timestamp to be updated + * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market + * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market */ function _setLastRewardingBlockTimestamp( VToken vToken, From 59b141362bb92ac0a7f2aa528107fd62f327abf0 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 11 Jan 2024 14:01:43 +0530 Subject: [PATCH 09/22] fix: VPB-02 confirmation on the handling of updated time-based contracts --- contracts/JumpRateModelV2.sol | 2 +- contracts/Lens/PoolLens.sol | 2 +- contracts/VToken.sol | 4 ++-- contracts/WhitePaperInterestRateModel.sol | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/JumpRateModelV2.sol b/contracts/JumpRateModelV2.sol index 9999e8b6c..4c6205139 100644 --- a/contracts/JumpRateModelV2.sol +++ b/contracts/JumpRateModelV2.sol @@ -12,7 +12,7 @@ import { EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; * @notice An interest rate model with a steep increase after a certain utilization threshold called **kink** is reached. * The parameters of this interest rate model can be adjusted by the owner. Version 2 modifies Version 1 by enabling updateable parameters */ -contract JumpRateModelV2 is TimeManagerV8, InterestRateModel { +contract JumpRateModelV2 is InterestRateModel, TimeManagerV8 { /** * @notice The address of the AccessControlManager contract */ diff --git a/contracts/Lens/PoolLens.sol b/contracts/Lens/PoolLens.sol index b42aa4544..589806514 100644 --- a/contracts/Lens/PoolLens.sol +++ b/contracts/Lens/PoolLens.sol @@ -26,7 +26,7 @@ import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeM - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken. */ -contract PoolLens is TimeManagerV8, ExponentialNoError { +contract PoolLens is ExponentialNoError, TimeManagerV8 { /** * @dev Struct for PoolDetails. */ diff --git a/contracts/VToken.sol b/contracts/VToken.sol index 28e10e30a..b6cbb9d1b 100644 --- a/contracts/VToken.sol +++ b/contracts/VToken.sol @@ -42,12 +42,12 @@ import { ensureNonzeroAddress } from "./lib/validators.sol"; * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below. */ contract VToken is - TimeManagerV8, Ownable2StepUpgradeable, AccessControlledV8, VTokenInterface, ExponentialNoError, - TokenErrorReporter + TokenErrorReporter, + TimeManagerV8 { using SafeERC20Upgradeable for IERC20Upgradeable; diff --git a/contracts/WhitePaperInterestRateModel.sol b/contracts/WhitePaperInterestRateModel.sol index d578b0418..c463101c9 100644 --- a/contracts/WhitePaperInterestRateModel.sol +++ b/contracts/WhitePaperInterestRateModel.sol @@ -10,7 +10,7 @@ import { EXP_SCALE, MANTISSA_ONE } from "./lib/constants.sol"; * @author Compound * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper */ -contract WhitePaperInterestRateModel is TimeManagerV8, InterestRateModel { +contract WhitePaperInterestRateModel is InterestRateModel, TimeManagerV8 { /** * @notice The multiplier of utilization rate per block or second that gives the slope of the interest rate */ From 1ab27b3fc7fc8d758197257dd76fcc709fa91c6a Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 11 Jan 2024 14:04:02 +0530 Subject: [PATCH 10/22] refactor: added natspec comments --- contracts/Shortfall/Shortfall.sol | 2 ++ contracts/VToken.sol | 1 + 2 files changed, 3 insertions(+) diff --git a/contracts/Shortfall/Shortfall.sol b/contracts/Shortfall/Shortfall.sol index c8efc1075..e404d8a21 100644 --- a/contracts/Shortfall/Shortfall.sol +++ b/contracts/Shortfall/Shortfall.sol @@ -165,6 +165,8 @@ contract Shortfall is /** * @param timeBased_ A boolean indicating whether the contract is based on time or block. * @param blocksPerYear_ The number of blocks per year + * @param nextBidderBlockOrTimestampLimit_ Default block or timestamp limit for the next bidder to place a bid + * @param waitForFirstBidder_ Default number of blocks or seconds to wait for the first bidder before starting the auction * @custom:oz-upgrades-unsafe-allow constructor */ constructor( diff --git a/contracts/VToken.sol b/contracts/VToken.sol index b6cbb9d1b..399ad9a9f 100644 --- a/contracts/VToken.sol +++ b/contracts/VToken.sol @@ -77,6 +77,7 @@ contract VToken is /** * @param timeBased_ A boolean indicating whether the contract is based on time or block. * @param blocksPerYear_ The number of blocks per year + * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa * @custom:oz-upgrades-unsafe-allow constructor */ constructor( From d6311f25cf84ac1c82a143109e45ad9fea1d4dc3 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Fri, 12 Jan 2024 14:43:49 +0530 Subject: [PATCH 11/22] refactor: move storage of shortfall and rewardsDistributor to separate storage contracts --- contracts/Rewards/RewardsDistributor.sol | 63 ++-------------- .../Rewards/RewardsDistributorStorage.sol | 75 +++++++++++++++++++ contracts/Shortfall/Shortfall.sol | 60 +-------------- contracts/Shortfall/ShortfallStorage.sol | 73 ++++++++++++++++++ 4 files changed, 157 insertions(+), 114 deletions(-) create mode 100644 contracts/Rewards/RewardsDistributorStorage.sol create mode 100644 contracts/Shortfall/ShortfallStorage.sol diff --git a/contracts/Rewards/RewardsDistributor.sol b/contracts/Rewards/RewardsDistributor.sol index 273c4e3d5..0840d4dd5 100644 --- a/contracts/Rewards/RewardsDistributor.sol +++ b/contracts/Rewards/RewardsDistributor.sol @@ -5,12 +5,13 @@ import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/acc import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol"; +import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; import { ExponentialNoError } from "../ExponentialNoError.sol"; import { VToken } from "../VToken.sol"; import { Comptroller } from "../Comptroller.sol"; import { MaxLoopsLimitHelper } from "../MaxLoopsLimitHelper.sol"; -import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; +import { RewardsDistributorStorage } from "./RewardsDistributorStorage.sol"; /** * @title `RewardsDistributor` @@ -28,72 +29,18 @@ import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeM * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors. */ contract RewardsDistributor is - TimeManagerV8, ExponentialNoError, Ownable2StepUpgradeable, AccessControlledV8, - MaxLoopsLimitHelper + MaxLoopsLimitHelper, + RewardsDistributorStorage, + TimeManagerV8 { using SafeERC20Upgradeable for IERC20Upgradeable; - struct RewardToken { - // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex - uint224 index; - // The block number the index was last updated at - uint32 block; - // The block number at which to stop rewards - uint32 lastRewardingBlock; - } - - struct TimeBasedRewardToken { - // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex - uint224 index; - // The block timestamp the index was last updated at - uint256 timestamp; - // The block timestamp at which to stop rewards - uint256 lastRewardingTimestamp; - } - /// @notice The initial REWARD TOKEN index for a market uint224 public constant INITIAL_INDEX = 1e36; - /// @notice The REWARD TOKEN market supply state for each market - mapping(address => RewardToken) public rewardTokenSupplyState; - - /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN - mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex; - - /// @notice The REWARD TOKEN accrued but not yet transferred to each user - mapping(address => uint256) public rewardTokenAccrued; - - /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second) - mapping(address => uint256) public rewardTokenBorrowSpeeds; - - /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second) - mapping(address => uint256) public rewardTokenSupplySpeeds; - - /// @notice The REWARD TOKEN market borrow state for each market - mapping(address => RewardToken) public rewardTokenBorrowState; - - /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second) - mapping(address => uint256) public rewardTokenContributorSpeeds; - - /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated - mapping(address => uint256) public lastContributorBlock; - - /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN - mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex; - - Comptroller private comptroller; - - IERC20Upgradeable public rewardToken; - - /// @notice The REWARD TOKEN market supply state for each market - mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased; - - /// @notice The REWARD TOKEN market borrow state for each market - mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased; - /// @notice Emitted when REWARD TOKEN is distributed to a supplier event DistributedSupplierRewardToken( VToken indexed vToken, diff --git a/contracts/Rewards/RewardsDistributorStorage.sol b/contracts/Rewards/RewardsDistributorStorage.sol new file mode 100644 index 000000000..c292c560b --- /dev/null +++ b/contracts/Rewards/RewardsDistributorStorage.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.13; + +import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; + +import { Comptroller } from "../Comptroller.sol"; + +/** + * @title RewardsDistributorStorage + * @author Venus + * @dev Storage for RewardsDistributor + */ +contract RewardsDistributorStorage { + struct RewardToken { + // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex + uint224 index; + // The block number the index was last updated at + uint32 block; + // The block number at which to stop rewards + uint32 lastRewardingBlock; + } + + struct TimeBasedRewardToken { + // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex + uint224 index; + // The block timestamp the index was last updated at + uint256 timestamp; + // The block timestamp at which to stop rewards + uint256 lastRewardingTimestamp; + } + + /// @notice The REWARD TOKEN market supply state for each market + mapping(address => RewardToken) public rewardTokenSupplyState; + + /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN + mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex; + + /// @notice The REWARD TOKEN accrued but not yet transferred to each user + mapping(address => uint256) public rewardTokenAccrued; + + /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second) + mapping(address => uint256) public rewardTokenBorrowSpeeds; + + /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second) + mapping(address => uint256) public rewardTokenSupplySpeeds; + + /// @notice The REWARD TOKEN market borrow state for each market + mapping(address => RewardToken) public rewardTokenBorrowState; + + /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second) + mapping(address => uint256) public rewardTokenContributorSpeeds; + + /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated + mapping(address => uint256) public lastContributorBlock; + + /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN + mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex; + + Comptroller internal comptroller; + + IERC20Upgradeable public rewardToken; + + /// @notice The REWARD TOKEN market supply state for each market + mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased; + + /// @notice The REWARD TOKEN market borrow state for each market + mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased; + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[37] private __gap; +} diff --git a/contracts/Shortfall/Shortfall.sol b/contracts/Shortfall/Shortfall.sol index e404d8a21..e6f61a460 100644 --- a/contracts/Shortfall/Shortfall.sol +++ b/contracts/Shortfall/Shortfall.sol @@ -16,6 +16,7 @@ import { IRiskFund } from "../RiskFund/IRiskFund.sol"; import { PoolRegistry } from "../Pool/PoolRegistry.sol"; import { PoolRegistryInterface } from "../Pool/PoolRegistryInterface.sol"; import { TokenDebtTracker } from "../lib/TokenDebtTracker.sol"; +import { ShortfallStorage } from "./ShortfallStorage.sol"; import { EXP_SCALE } from "../lib/constants.sol"; /** @@ -29,44 +30,15 @@ import { EXP_SCALE } from "../lib/constants.sol"; * risk fund in exchange for paying off all the pool's bad debt. */ contract Shortfall is - TimeManagerV8, Ownable2StepUpgradeable, AccessControlledV8, ReentrancyGuardUpgradeable, - TokenDebtTracker + TokenDebtTracker, + ShortfallStorage, + TimeManagerV8 { using SafeERC20Upgradeable for IERC20Upgradeable; - /// @notice Type of auction - enum AuctionType { - LARGE_POOL_DEBT, - LARGE_RISK_FUND - } - - /// @notice Status of auction - enum AuctionStatus { - NOT_STARTED, - STARTED, - ENDED - } - - /// @notice Auction metadata - struct Auction { - /// @notice It holds either the starting block number or timestamp - uint256 startBlockOrTimestamp; - AuctionType auctionType; - AuctionStatus status; - VToken[] markets; - uint256 seizedRiskFund; - address highestBidder; - uint256 highestBidBps; - /// @notice It holds either the highestBid block or timestamp - uint256 highestBidBlockOrTimestamp; - uint256 startBidBps; - mapping(VToken => uint256) marketDebt; - mapping(VToken => uint256) bidAmount; - } - /// @dev Max basis points i.e., 100% uint256 private constant MAX_BPS = 10000; @@ -81,30 +53,6 @@ contract Shortfall is /// @custom:oz-upgrades-unsafe-allow state-variable-immutable uint256 private immutable DEFAULT_WAIT_FOR_FIRST_BIDDER; - /// @notice Pool registry address - address public poolRegistry; - - /// @notice Risk fund address - IRiskFund public riskFund; - - /// @notice Minimum USD debt in pool for shortfall to trigger - uint256 public minimumPoolBadDebt; - - /// @notice Incentive to auction participants, initial value set to 1000 or 10% - uint256 public incentiveBps; - - /// @notice Time to wait for next bidder. Initially waits for 100 blocks or 300 seconds - uint256 public nextBidderBlockLimit; - - /// @notice Boolean of if auctions are paused - bool public auctionsPaused; - - /// @notice Time to wait for first bidder. Initially waits for 100 blocks or 300 seconds - uint256 public waitForFirstBidder; - - /// @notice Auctions for each pool - mapping(address => Auction) public auctions; - /// @notice Emitted when a auction starts event AuctionStarted( address indexed comptroller, diff --git a/contracts/Shortfall/ShortfallStorage.sol b/contracts/Shortfall/ShortfallStorage.sol new file mode 100644 index 000000000..e069332e9 --- /dev/null +++ b/contracts/Shortfall/ShortfallStorage.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.13; + +import { VToken } from "../VToken.sol"; +import { IRiskFund } from "../RiskFund/IRiskFund.sol"; + +/** + * @title ShortfallStorage + * @author Venus + * @dev Storage for Shortfall + */ +contract ShortfallStorage { + /// @notice Type of auction + enum AuctionType { + LARGE_POOL_DEBT, + LARGE_RISK_FUND + } + + /// @notice Status of auction + enum AuctionStatus { + NOT_STARTED, + STARTED, + ENDED + } + + /// @notice Auction metadata + struct Auction { + /// @notice It holds either the starting block number or timestamp + uint256 startBlockOrTimestamp; + AuctionType auctionType; + AuctionStatus status; + VToken[] markets; + uint256 seizedRiskFund; + address highestBidder; + uint256 highestBidBps; + /// @notice It holds either the highestBid block or timestamp + uint256 highestBidBlockOrTimestamp; + uint256 startBidBps; + mapping(VToken => uint256) marketDebt; + mapping(VToken => uint256) bidAmount; + } + + /// @notice Pool registry address + address public poolRegistry; + + /// @notice Risk fund address + IRiskFund public riskFund; + + /// @notice Minimum USD debt in pool for shortfall to trigger + uint256 public minimumPoolBadDebt; + + /// @notice Incentive to auction participants, initial value set to 1000 or 10% + uint256 public incentiveBps; + + /// @notice Time to wait for next bidder. Initially waits for 100 blocks or 300 seconds + uint256 public nextBidderBlockLimit; + + /// @notice Boolean of if auctions are paused + bool public auctionsPaused; + + /// @notice Time to wait for first bidder. Initially waits for 100 blocks or 300 seconds + uint256 public waitForFirstBidder; + + /// @notice Auctions for each pool + mapping(address => Auction) public auctions; + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[42] private __gap; +} From c749e0d6d301357876806274d244e06da0cb8108 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Fri, 12 Jan 2024 14:44:44 +0530 Subject: [PATCH 12/22] feat: add function to pick borrow rate and bidder values according to networks --- deploy/009-deploy-vtokens.ts | 4 +- deploy/014-riskfund-protocolshare.ts | 6 +- deploy/016-deploy-beacon-implementations.ts | 3 +- helpers/deploymentConfig.ts | 93 ++++++++++++++++++++- 4 files changed, 99 insertions(+), 7 deletions(-) diff --git a/deploy/009-deploy-vtokens.ts b/deploy/009-deploy-vtokens.ts index f5201c8b0..cfe5fcb72 100644 --- a/deploy/009-deploy-vtokens.ts +++ b/deploy/009-deploy-vtokens.ts @@ -5,7 +5,7 @@ import { DeployResult } from "hardhat-deploy/dist/types"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { getConfig, getTokenConfig } from "../helpers/deploymentConfig"; +import { getConfig, getMaxBorrowRateMantissa, getTokenConfig } from "../helpers/deploymentConfig"; import { InterestRateModels } from "../helpers/deploymentConfig"; import { getBlockOrTimestampBasedDeploymentInfo, getUnregisteredVTokens, toAddress } from "../helpers/deploymentUtils"; import { AddressOne } from "../helpers/utils"; @@ -21,7 +21,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { tokensConfig, poolConfig, preconfiguredAddresses } = await getConfig(hre.network.name); const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.network.name); - const maxBorrowRateMantissa = BigNumber.from(0.0005e16); + const maxBorrowRateMantissa = getMaxBorrowRateMantissa(hre.network.name); const accessControlManagerAddress = await toAddress( preconfiguredAddresses.AccessControlManager || "AccessControlManager", diff --git a/deploy/014-riskfund-protocolshare.ts b/deploy/014-riskfund-protocolshare.ts index ec195960a..85313c9e6 100644 --- a/deploy/014-riskfund-protocolshare.ts +++ b/deploy/014-riskfund-protocolshare.ts @@ -3,7 +3,7 @@ import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { getConfig } from "../helpers/deploymentConfig"; +import { getBidderDeploymentValues, getConfig } from "../helpers/deploymentConfig"; import { getBlockOrTimestampBasedDeploymentInfo, getUnderlyingToken, toAddress } from "../helpers/deploymentUtils"; import { convertToUnit } from "../helpers/utils"; import { Comptroller } from "../typechain"; @@ -11,8 +11,6 @@ import { Comptroller } from "../typechain"; const MIN_AMOUNT_TO_CONVERT = convertToUnit(10, 18); const MIN_POOL_BAD_DEBT = convertToUnit(1000, 18); const maxLoopsLimit = 100; -const waitForFirstBidder = 100; // for block based contracts deployment -const nextBidderBlockOrTimestampLimit = 100; // for block based contracts deployment const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments, getNamedAccounts } = hre; @@ -23,6 +21,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.network.name); + const { waitForFirstBidder, nextBidderBlockOrTimestampLimit } = getBidderDeploymentValues(hre.network.name); + const poolRegistry = await ethers.getContract("PoolRegistry"); const deployerSigner = ethers.provider.getSigner(deployer); const swapRouterAddress = await toAddress(preconfiguredAddresses.SwapRouter_CorePool || "SwapRouter", hre); diff --git a/deploy/016-deploy-beacon-implementations.ts b/deploy/016-deploy-beacon-implementations.ts index 2fb722921..36ca1451a 100644 --- a/deploy/016-deploy-beacon-implementations.ts +++ b/deploy/016-deploy-beacon-implementations.ts @@ -2,6 +2,7 @@ import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { getMaxBorrowRateMantissa } from "../helpers/deploymentConfig"; import { getBlockOrTimestampBasedDeploymentInfo } from "../helpers/deploymentUtils"; // This deploy script deploys implementations for Comptroller and/or VToken that should be updated through a VIP afterwards @@ -13,7 +14,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.network.name); const poolRegistry = await ethers.getContract("PoolRegistry"); - const maxBorrowRateMantissa = ethers.BigNumber.from(0.0005e16); + const maxBorrowRateMantissa = getMaxBorrowRateMantissa(hre.network.name); // Comptroller Implementation await deploy("ComptrollerImpl", { diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 18302d7db..a455fefee 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -8,6 +8,7 @@ import { contracts as venusProtocolBscTestnet } from "@venusprotocol/venus-proto import { contracts as venusProtocolEthereum } from "@venusprotocol/venus-protocol/deployments/ethereum.json"; import { contracts as venusProtocolOpbnbTestnet } from "@venusprotocol/venus-protocol/deployments/opbnbtestnet.json"; import { contracts as venusProtocolSepolia } from "@venusprotocol/venus-protocol/deployments/sepolia.json"; +import { BigNumber } from "ethers"; import { ethers } from "hardhat"; import { DeploymentsExtension } from "hardhat-deploy/types"; @@ -36,6 +37,11 @@ export type DeploymentInfo = { blocksPerYear: number; }; +type BidderDeploymentValues = { + waitForFirstBidder: number; + nextBidderBlockOrTimestampLimit: number; +}; + export type TokenConfig = { isMock: boolean; name?: string; @@ -116,7 +122,7 @@ export const blocksPerYear: BlocksPerYear = { sepolia: ETH_BLOCKS_PER_YEAR, ethereum: ETH_BLOCKS_PER_YEAR, opbnbtestnet: OPBNB_BLOCKS_PER_YEAR, - isTimeBased: SECONDS_PER_YEAR, + isTimeBased: 0, }; export const SEPOLIA_MULTISIG = "0x94fa6078b6b8a26f0b6edffbe6501b22a10470fb"; @@ -3089,3 +3095,88 @@ export async function getTokenAddress(tokenConfig: TokenConfig, deployments: Dep return tokenConfig.tokenAddress; } } + +export function getBidderDeploymentValues(networkName: string): BidderDeploymentValues { + const isTimeBased = process.env.IS_TIME_BASED_DEPLOYMENT === "true"; + + if (isTimeBased) { + return { + waitForFirstBidder: 300, + nextBidderBlockOrTimestampLimit: 300, + }; + } + + switch (networkName) { + case "hardhat": + return { + waitForFirstBidder: 100, + nextBidderBlockOrTimestampLimit: 100, + }; + case "bsctestnet": + return { + waitForFirstBidder: 100, + nextBidderBlockOrTimestampLimit: 100, + }; + case "bscmainnet": + return { + waitForFirstBidder: 100, + nextBidderBlockOrTimestampLimit: 100, + }; + case "sepolia": + return { + waitForFirstBidder: 25, + nextBidderBlockOrTimestampLimit: 25, + }; + case "ethereum": + return { + waitForFirstBidder: 25, + nextBidderBlockOrTimestampLimit: 25, + }; + case "opbnbtestnet": + return { + waitForFirstBidder: 300, + nextBidderBlockOrTimestampLimit: 300, + }; + case "opbnbmainnet": + return { + waitForFirstBidder: 300, + nextBidderBlockOrTimestampLimit: 300, + }; + case "development": + return { + waitForFirstBidder: 100, + nextBidderBlockOrTimestampLimit: 100, + }; + default: + throw new Error(`bidder limits for network ${networkName} is not available.`); + } +} + +export function getMaxBorrowRateMantissa(networkName: string): BigNumber { + const isTimeBased = process.env.IS_TIME_BASED_DEPLOYMENT === "true"; + + if (isTimeBased) { + return BigNumber.from(0.00016667e16); // (0.0005e16 / 3) for per second + } + + switch (networkName) { + case "hardhat": + return BigNumber.from(0.0005e16); + case "bsctestnet": + return BigNumber.from(0.0005e16); + case "bscmainnet": + return BigNumber.from(0.0005e16); + case "sepolia": + return BigNumber.from(0.0005e16); + case "ethereum": + return BigNumber.from(0.0005e16); + case "opbnbtestnet": + return BigNumber.from(0.0005e16); + case "opbnbmainnet": + return BigNumber.from(0.0005e16); + case "development": + return BigNumber.from(0.0005e16); + default: + throw new Error(`max borrow rate for network ${networkName} is not available.`); + } +} From 408f0339207663b027c8af45690f9267a671af60 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 15 Jan 2024 13:00:17 +0530 Subject: [PATCH 13/22] fixup: SSV-01 block number-based variables should be made immutable --- contracts/Shortfall/ShortfallStorage.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Shortfall/ShortfallStorage.sol b/contracts/Shortfall/ShortfallStorage.sol index e069332e9..ee4822021 100644 --- a/contracts/Shortfall/ShortfallStorage.sol +++ b/contracts/Shortfall/ShortfallStorage.sol @@ -52,13 +52,13 @@ contract ShortfallStorage { /// @notice Incentive to auction participants, initial value set to 1000 or 10% uint256 public incentiveBps; - /// @notice Time to wait for next bidder. Initially waits for 100 blocks or 300 seconds + /// @notice Time to wait for next bidder. Initially waits for DEFAULT_NEXT_BIDDER_BLOCK_OR_TIMESTAMP_LIMIT uint256 public nextBidderBlockLimit; /// @notice Boolean of if auctions are paused bool public auctionsPaused; - /// @notice Time to wait for first bidder. Initially waits for 100 blocks or 300 seconds + /// @notice Time to wait for first bidder. Initially waits for DEFAULT_WAIT_FOR_FIRST_BIDDER uint256 public waitForFirstBidder; /// @notice Auctions for each pool From e16e4c7cf0283295602c38847a24f56a9d7900d1 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 15 Jan 2024 13:17:23 +0530 Subject: [PATCH 14/22] fixup: VPB-01 value naming should be updated to reflect possible time-based case for vToken --- contracts/VToken.sol | 56 +++++++++++++++++----------------- contracts/VTokenInterfaces.sol | 2 +- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/contracts/VToken.sol b/contracts/VToken.sol index 399ad9a9f..549ee77f0 100644 --- a/contracts/VToken.sol +++ b/contracts/VToken.sol @@ -56,7 +56,7 @@ contract VToken is // Maximum fraction of interest that can be set aside for reserves uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18; - // Maximum borrow rate that can ever be applied (.0005% / slot(block or second)) + // Maximum borrow rate that can ever be applied per slot(block or second) /// @custom:oz-upgrades-unsafe-allow state-variable-immutable uint256 internal immutable MAX_BORROW_RATE_MANTISSA; @@ -633,15 +633,15 @@ contract VToken is } /** - * @notice A public function to set new threshold of slot(block/second) difference after which funds will be sent to the protocol share reserve - * @param _newReduceReservesBlockDelta slot(block/second) difference value + * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve + * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value * @custom:access Only Governance */ - function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockDelta) external { + function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external { _checkAccessAllowed("setReduceReservesBlockDelta(uint256)"); - require(_newReduceReservesBlockDelta > 0, "Invalid Input"); - emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockDelta); - reduceReservesBlockDelta = _newReduceReservesBlockDelta; + require(_newReduceReservesBlockOrTimestampDelta > 0, "Invalid Input"); + emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta); + reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta; } /** @@ -692,16 +692,16 @@ contract VToken is } /** - * @notice Returns the current per-slot(block/second) borrow interest rate for this vToken - * @return rate The borrow interest rate per slot(block/second), scaled by 1e18 + * @notice Returns the current per slot(block or second) borrow interest rate for this vToken + * @return rate The borrow interest rate per slot(block or second), scaled by 1e18 */ function borrowRatePerBlock() external view override returns (uint256) { return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt); } /** - * @notice Returns the current per-slot(block/second) supply interest rate for this v - * @return rate The supply interest rate per slot(block/second), scaled by 1e18 + * @notice Returns the current per-slot(block or second) supply interest rate for this v + * @return rate The supply interest rate per slot(block or second), scaled by 1e18 */ function supplyRatePerBlock() external view override returns (uint256) { return @@ -743,8 +743,8 @@ contract VToken is /** * @notice Applies accrued interest to total borrows and reserves - * @dev This calculates interest accrued from the last checkpointed slot(block/second) - * up to the current slot(block/second) and writes new checkpoint to storage and + * @dev This calculates interest accrued from the last checkpointed slot(block or second) + * up to the current slot(block or second) and writes new checkpoint to storage and * reduce spread reserves to protocol share reserve * if currentSlot - reduceReservesBlockNumber >= slotDelta * @return Always NO_ERROR @@ -752,7 +752,7 @@ contract VToken is * @custom:access Not restricted */ function accrueInterest() public virtual override returns (uint256) { - /* Remember the initial block number */ + /* Remember the initial block number or timestamp */ uint256 currentSlotNumber = getBlockNumberOrTimestamp(); uint256 accrualSlotNumberPrior = accrualBlockNumber; @@ -816,7 +816,7 @@ contract VToken is /** * @notice User supplies assets into the market and receives vTokens in exchange - * @dev Assumes interest has already been accrued up to the current block + * @dev Assumes interest has already been accrued up to the current block or timestamp * @param payer The address of the account which is sending the assets for supply * @param minter The address of the account which is supplying the assets * @param mintAmount The amount of the underlying asset to supply @@ -825,7 +825,7 @@ contract VToken is /* Fail if mint not allowed */ comptroller.preMintHook(address(this), minter, mintAmount); - /* Verify market's slot(block/second) number equals current slot(block/second) number */ + /* Verify market's slot(block or second) number equals current slot(block or second) number */ if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert MintFreshnessCheck(); } @@ -872,7 +872,7 @@ contract VToken is /** * @notice User redeems vTokens in exchange for the underlying asset - * @dev Assumes interest has already been accrued up to the current slot(block/second) + * @dev Assumes interest has already been accrued up to the current slot(block or second) * @param redeemer The address of the account which is redeeming the tokens * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero) * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero) @@ -880,7 +880,7 @@ contract VToken is function _redeemFresh(address redeemer, uint256 redeemTokensIn, uint256 redeemAmountIn) internal { require(redeemTokensIn == 0 || redeemAmountIn == 0, "one of redeemTokensIn or redeemAmountIn must be zero"); - /* Verify market's slot(block/second) number equals current slot(block/second) number */ + /* Verify market's slot(block or second) number equals current slot(block or second) number */ if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert RedeemFreshnessCheck(); } @@ -961,7 +961,7 @@ contract VToken is /* Fail if borrow not allowed */ comptroller.preBorrowHook(address(this), borrower, borrowAmount); - /* Verify market's slot(block/second) number equals current slot(block/second) number */ + /* Verify market's slot(block or second) number equals current slot(block or second) number */ if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert BorrowFreshnessCheck(); } @@ -1017,7 +1017,7 @@ contract VToken is /* Fail if repayBorrow not allowed */ comptroller.preRepayHook(address(this), borrower); - /* Verify market's slot(block/second) number equals current slot(block/second) number */ + /* Verify market's slot(block or second) number equals current slot(block or second) number */ if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert RepayBorrowFreshnessCheck(); } @@ -1116,12 +1116,12 @@ contract VToken is skipLiquidityCheck ); - /* Verify market's slot(block/second) number equals current slot(block/second) number */ + /* Verify market's slot(block or second) number equals current slot(block or second) number */ if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert LiquidateFreshnessCheck(); } - /* Verify vTokenCollateral market's slot(block/second) number equals current slot(block/second) number */ + /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */ if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) { revert LiquidateCollateralFreshnessCheck(); } @@ -1257,7 +1257,7 @@ contract VToken is * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18) */ function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal { - // Verify market's slot(block/second) number equals current slot(block/second) number + // Verify market's slot(block or second) number equals current slot(block or second) number if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert SetReserveFactorFreshCheck(); } @@ -1284,7 +1284,7 @@ contract VToken is uint256 totalReservesNew; uint256 actualAddAmount; - // We fail gracefully unless market's slot(block/second) number equals current slot(block/second) number + // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert AddReservesFactorFreshCheck(actualAddAmount); } @@ -1309,7 +1309,7 @@ contract VToken is // totalReserves - reduceAmount uint256 totalReservesNew; - // We fail gracefully unless market's slot(block/second) number equals current slot(block/second) number + // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert ReduceReservesFreshCheck(); } @@ -1356,7 +1356,7 @@ contract VToken is // Used to store old model for use in the event that is emitted on success InterestRateModel oldInterestRateModel; - // We fail gracefully unless market's slot(block/second) number equals current slot(block/second) number + // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number if (accrualBlockNumber != getBlockNumberOrTimestamp()) { revert SetInterestRateModelFreshCheck(); } @@ -1489,11 +1489,11 @@ contract VToken is _setComptroller(comptroller_); - // Initialize slot(block/second) number and borrow index (slot(block/second) number mocks depend on comptroller being set) + // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set) accrualBlockNumber = getBlockNumberOrTimestamp(); borrowIndex = MANTISSA_ONE; - // Set the interest rate model (depends on slot(block/second) number / borrow index) + // Set the interest rate model (depends on slot(block or second) number / borrow index) _setInterestRateModelFresh(interestRateModel_); _setReserveFactorFresh(reserveFactorMantissa_); diff --git a/contracts/VTokenInterfaces.sol b/contracts/VTokenInterfaces.sol index e3e2d1304..42d926053 100644 --- a/contracts/VTokenInterfaces.sol +++ b/contracts/VTokenInterfaces.sol @@ -73,7 +73,7 @@ contract VTokenStorage { uint256 public reserveFactorMantissa; /** - * @notice Slot(block/second) number that interest was last accrued at + * @notice Slot(block or second) number that interest was last accrued at */ uint256 public accrualBlockNumber; From 1a6cf0c1aea867cef4657670fb989dbc0b47c91c Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Mon, 26 Feb 2024 19:51:02 +0530 Subject: [PATCH 15/22] fix: scope 1 fetch TimeBased mappings from reward distributor in pool lens --- contracts/Lens/PoolLens.sol | 38 +++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/contracts/Lens/PoolLens.sol b/contracts/Lens/PoolLens.sol index 589806514..632b79c07 100644 --- a/contracts/Lens/PoolLens.sol +++ b/contracts/Lens/PoolLens.sol @@ -445,20 +445,38 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { RewardsDistributor rewardsDistributor ) internal view returns (PendingReward[] memory) { PendingReward[] memory pendingRewards = new PendingReward[](markets.length); + + bool isTimeBased = rewardsDistributor.isTimeBased(); + for (uint256 i; i < markets.length; ++i) { // Market borrow and supply state we will modify update in-memory, in order to not modify storage RewardTokenState memory borrowState; - ( - borrowState.index, - borrowState.blockOrTimestamp, - borrowState.lastRewardingBlockOrTimestamp - ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i])); RewardTokenState memory supplyState; - ( - supplyState.index, - supplyState.blockOrTimestamp, - supplyState.lastRewardingBlockOrTimestamp - ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i])); + + if (isTimeBased) { + ( + borrowState.index, + borrowState.blockOrTimestamp, + borrowState.lastRewardingBlockOrTimestamp + ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i])); + ( + supplyState.index, + supplyState.blockOrTimestamp, + supplyState.lastRewardingBlockOrTimestamp + ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i])); + } else { + ( + borrowState.index, + borrowState.blockOrTimestamp, + borrowState.lastRewardingBlockOrTimestamp + ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i])); + ( + supplyState.index, + supplyState.blockOrTimestamp, + supplyState.lastRewardingBlockOrTimestamp + ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i])); + } + Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() }); // Update market supply and borrow index in-memory From 4626a1032510390627728a998b0aa19e8eaa3682 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 13 Mar 2024 13:20:43 +0530 Subject: [PATCH 16/22] fix: VTIME-5 --- contracts/Rewards/RewardsDistributor.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Rewards/RewardsDistributor.sol b/contracts/Rewards/RewardsDistributor.sol index 0840d4dd5..36a686ca0 100644 --- a/contracts/Rewards/RewardsDistributor.sol +++ b/contracts/Rewards/RewardsDistributor.sol @@ -220,7 +220,7 @@ contract RewardsDistributor is uint32[] calldata supplyLastRewardingBlocks, uint32[] calldata borrowLastRewardingBlocks ) external { - _checkAccessAllowed("setLastRewardingBlock(address[],uint32[],uint32[])"); + _checkAccessAllowed("setLastRewardingBlocks(address[],uint32[],uint32[])"); require(!isTimeBased, "Block-based operation only"); uint256 numTokens = vTokens.length; From e57c00d7df5f84d4eb19e10d6cf2704d18b0fdff Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 13 Mar 2024 15:20:20 +0530 Subject: [PATCH 17/22] fix: VTIME-4 --- contracts/Lens/PoolLens.sol | 5 +- tests/hardhat/Lens/RewardsSummary.ts | 98 +++++++++++++++++++--------- 2 files changed, 71 insertions(+), 32 deletions(-) diff --git a/contracts/Lens/PoolLens.sol b/contracts/Lens/PoolLens.sol index 632b79c07..83ad7074d 100644 --- a/contracts/Lens/PoolLens.sol +++ b/contracts/Lens/PoolLens.sol @@ -446,14 +446,15 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { ) internal view returns (PendingReward[] memory) { PendingReward[] memory pendingRewards = new PendingReward[](markets.length); - bool isTimeBased = rewardsDistributor.isTimeBased(); + bool _isTimeBased = rewardsDistributor.isTimeBased(); + require(_isTimeBased == isTimeBased, "Inconsistent Reward mode"); for (uint256 i; i < markets.length; ++i) { // Market borrow and supply state we will modify update in-memory, in order to not modify storage RewardTokenState memory borrowState; RewardTokenState memory supplyState; - if (isTimeBased) { + if (_isTimeBased) { ( borrowState.index, borrowState.blockOrTimestamp, diff --git a/tests/hardhat/Lens/RewardsSummary.ts b/tests/hardhat/Lens/RewardsSummary.ts index 0410c1d32..b6eca1e25 100644 --- a/tests/hardhat/Lens/RewardsSummary.ts +++ b/tests/hardhat/Lens/RewardsSummary.ts @@ -67,6 +67,7 @@ const rewardsFixture = async (): Promise => { rewardDistributor3.address, ]); + rewardDistributor1.isTimeBased.returns(false); rewardDistributor1.rewardToken.returns(rewardToken1.address); rewardDistributor1.rewardTokenBorrowerIndex.returns(convertToUnit(1, 18)); rewardDistributor1.rewardTokenSupplierIndex.returns(convertToUnit(1, 18)); @@ -86,6 +87,7 @@ const rewardsFixture = async (): Promise => { lastRewardingBlock: 0, }); + rewardDistributor2.isTimeBased.returns(false); rewardDistributor2.rewardToken.returns(rewardToken2.address); rewardDistributor2.rewardTokenBorrowerIndex.returns(convertToUnit(1, 18)); rewardDistributor2.rewardTokenSupplierIndex.returns(convertToUnit(1, 18)); @@ -105,6 +107,7 @@ const rewardsFixture = async (): Promise => { lastRewardingBlock: 0, }); + rewardDistributor3.isTimeBased.returns(false); rewardDistributor3.rewardToken.returns(rewardToken3.address); rewardDistributor3.rewardTokenBorrowerIndex.returns(convertToUnit(1, 18)); rewardDistributor3.rewardTokenSupplierIndex.returns(convertToUnit(1, 18)); @@ -178,6 +181,7 @@ const timeBasedRewardsFixture = async (): Promise => { rewardDistributor3.address, ]); + rewardDistributor1.isTimeBased.returns(true); rewardDistributor1.rewardToken.returns(rewardToken1.address); rewardDistributor1.rewardTokenBorrowerIndex.returns(convertToUnit(1, 18)); rewardDistributor1.rewardTokenSupplierIndex.returns(convertToUnit(1, 18)); @@ -186,17 +190,18 @@ const timeBasedRewardsFixture = async (): Promise => { rewardDistributor1.rewardTokenSupplySpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); rewardDistributor1.rewardTokenBorrowSpeeds.whenCalledWith(vBUSD.address).returns(convertToUnit(0.5, 18)); rewardDistributor1.rewardTokenBorrowSpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); - rewardDistributor1.rewardTokenBorrowState.returns({ + rewardDistributor1.rewardTokenBorrowStateTimeBased.returns({ index: convertToUnit(1, 18), - block: startBlockTimestamp, - lastRewardingBlock: 0, + timestamp: startBlockTimestamp, + lastRewardingTimestamp: 0, }); - rewardDistributor1.rewardTokenSupplyState.returns({ + rewardDistributor1.rewardTokenSupplyStateTimeBased.returns({ index: convertToUnit(1, 18), - block: startBlockTimestamp, - lastRewardingBlock: 0, + timestamp: startBlockTimestamp, + lastRewardingTimestamp: 0, }); + rewardDistributor2.isTimeBased.returns(true); rewardDistributor2.rewardToken.returns(rewardToken2.address); rewardDistributor2.rewardTokenBorrowerIndex.returns(convertToUnit(1, 18)); rewardDistributor2.rewardTokenSupplierIndex.returns(convertToUnit(1, 18)); @@ -205,17 +210,18 @@ const timeBasedRewardsFixture = async (): Promise => { rewardDistributor2.rewardTokenSupplySpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); rewardDistributor2.rewardTokenBorrowSpeeds.whenCalledWith(vBUSD.address).returns(convertToUnit(0.5, 18)); rewardDistributor2.rewardTokenBorrowSpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); - rewardDistributor2.rewardTokenBorrowState.returns({ + rewardDistributor2.rewardTokenBorrowStateTimeBased.returns({ index: convertToUnit(1, 18), - block: startBlockTimestamp, - lastRewardingBlock: 0, + timestamp: startBlockTimestamp, + lastRewardingTimestamp: 0, }); - rewardDistributor2.rewardTokenSupplyState.returns({ + rewardDistributor2.rewardTokenSupplyStateTimeBased.returns({ index: convertToUnit(1, 18), - block: startBlockTimestamp, - lastRewardingBlock: 0, + timestamp: startBlockTimestamp, + lastRewardingTimestamp: 0, }); + rewardDistributor3.isTimeBased.returns(true); rewardDistributor3.rewardToken.returns(rewardToken3.address); rewardDistributor3.rewardTokenBorrowerIndex.returns(convertToUnit(1, 18)); rewardDistributor3.rewardTokenSupplierIndex.returns(convertToUnit(1, 18)); @@ -224,15 +230,15 @@ const timeBasedRewardsFixture = async (): Promise => { rewardDistributor3.rewardTokenSupplySpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); rewardDistributor3.rewardTokenBorrowSpeeds.whenCalledWith(vBUSD.address).returns(convertToUnit(0.5, 18)); rewardDistributor3.rewardTokenBorrowSpeeds.whenCalledWith(vWBTC.address).returns(convertToUnit(0.5, 18)); - rewardDistributor3.rewardTokenBorrowState.returns({ + rewardDistributor3.rewardTokenBorrowStateTimeBased.returns({ index: convertToUnit(1, 18), - block: startBlockTimestamp, - lastRewardingBlock: 0, + timestamp: startBlockTimestamp, + lastRewardingTimestamp: 0, }); - rewardDistributor3.rewardTokenSupplyState.returns({ + rewardDistributor3.rewardTokenSupplyStateTimeBased.returns({ index: convertToUnit(1, 18), - block: startBlockTimestamp, - lastRewardingBlock: 0, + timestamp: startBlockTimestamp, + lastRewardingTimestamp: 0, }); vBUSD.borrowIndex.returns(convertToUnit(1, 18)); @@ -295,6 +301,7 @@ for (const isTimeBased of [false, true]) { const accountAddress = await account.getAddress(); const pendingRewards = await poolLens.getPendingRewards(accountAddress, comptroller.address); + expect(comptroller.getAllMarkets).to.have.been.calledOnce; expect(comptroller.getRewardDistributors).to.have.been.calledOnce; @@ -307,13 +314,23 @@ for (const isTimeBased of [false, true]) { expect(rewardDistributor3.rewardTokenAccrued).to.have.been.calledOnce; // Should be called once per market - expect(rewardDistributor1.rewardTokenBorrowState).to.have.been.callCount(2); - expect(rewardDistributor2.rewardTokenBorrowState).to.have.been.callCount(2); - expect(rewardDistributor3.rewardTokenBorrowState).to.have.been.callCount(2); - - expect(rewardDistributor1.rewardTokenSupplyState).to.have.been.callCount(2); - expect(rewardDistributor2.rewardTokenSupplyState).to.have.been.callCount(2); - expect(rewardDistributor3.rewardTokenSupplyState).to.have.been.callCount(2); + if (isTimeBased) { + expect(rewardDistributor1.rewardTokenBorrowStateTimeBased).to.have.been.callCount(2); + expect(rewardDistributor2.rewardTokenBorrowStateTimeBased).to.have.been.callCount(2); + expect(rewardDistributor3.rewardTokenBorrowStateTimeBased).to.have.been.callCount(2); + + expect(rewardDistributor1.rewardTokenSupplyStateTimeBased).to.have.been.callCount(2); + expect(rewardDistributor2.rewardTokenSupplyStateTimeBased).to.have.been.callCount(2); + expect(rewardDistributor3.rewardTokenSupplyStateTimeBased).to.have.been.callCount(2); + } else { + expect(rewardDistributor1.rewardTokenBorrowState).to.have.been.callCount(2); + expect(rewardDistributor2.rewardTokenBorrowState).to.have.been.callCount(2); + expect(rewardDistributor3.rewardTokenBorrowState).to.have.been.callCount(2); + + expect(rewardDistributor1.rewardTokenSupplyState).to.have.been.callCount(2); + expect(rewardDistributor2.rewardTokenSupplyState).to.have.been.callCount(2); + expect(rewardDistributor3.rewardTokenSupplyState).to.have.been.callCount(2); + } // Should be called once per reward token configured expect(vBUSD.borrowIndex).to.have.been.callCount(3); @@ -362,12 +379,18 @@ for (const isTimeBased of [false, true]) { let blockNumberOrTimestamp = (await ethers.provider.getBlock("latest")).number; if (isTimeBased) { blockNumberOrTimestamp = (await ethers.provider.getBlock("latest")).timestamp; + rewardDistributor3.rewardTokenBorrowStateTimeBased.returns({ + index: convertToUnit(1, 36), // Current index is 1.0, double scale + timestamp: blockNumberOrTimestamp, + lastRewardingTimestamp: 0, + }); + } else { + rewardDistributor3.rewardTokenBorrowState.returns({ + index: convertToUnit(1, 36), // Current index is 1.0, double scale + block: blockNumberOrTimestamp, + lastRewardingBlock: 0, + }); } - rewardDistributor3.rewardTokenBorrowState.returns({ - index: convertToUnit(1, 36), // Current index is 1.0, double scale - block: blockNumberOrTimestamp, - lastRewardingBlock: 0, - }); rewardDistributor3.INITIAL_INDEX.returns(convertToUnit(0.6, 36)); // Should start accruing rewards at 0.6 of the current index const pendingRewards = await poolLens.getPendingRewards(await account.getAddress(), comptroller.address); @@ -395,5 +418,20 @@ for (const isTimeBased of [false, true]) { ]; expect(pendingRewards).to.have.deep.members(EXPECTED_OUTPUT); }); + + it("Should revert when mode of PoolLens and RewardsDistributor differ", async () => { + await mineUpTo(startBlock + 1000); + + const accountAddress = await account.getAddress(); + + if (isTimeBased) { + rewardDistributor3.isTimeBased.returns(false); + } else { + rewardDistributor3.isTimeBased.returns(true); + } + await expect(poolLens.getPendingRewards(accountAddress, comptroller.address)).to.be.revertedWith( + "Inconsistent Reward mode", + ); + }); }); } From d61191cb1a8c198deea6cc362425144efbc312f5 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 13 Mar 2024 15:53:26 +0530 Subject: [PATCH 18/22] fix: VTIME-3 --- contracts/VToken.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/VToken.sol b/contracts/VToken.sol index 748415677..17e312dc9 100644 --- a/contracts/VToken.sol +++ b/contracts/VToken.sol @@ -87,6 +87,8 @@ contract VToken is ) TimeManagerV8(timeBased_, blocksPerYear_) { // Note that the contract is upgradeable. Use initialize() or reinitializers // to set the state variables. + require(maxBorrowRateMantissa_ <= 1e18, "Max borrow rate must be <= 1e18"); + MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_; _disableInitializers(); } From aa1f7ae61b07839231ec16e9c4143905785d7aae Mon Sep 17 00:00:00 2001 From: Jesus Lanchas Date: Sun, 17 Mar 2024 21:05:36 +0100 Subject: [PATCH 19/22] docs: add audit reports from Fairyproof and Certik about time based contracts --- audits/088_timeBased_certik_20240117.pdf | Bin 0 -> 1678043 bytes audits/094_timeBased_fairyproof_20240304.pdf | Bin 0 -> 377114 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 audits/088_timeBased_certik_20240117.pdf create mode 100644 audits/094_timeBased_fairyproof_20240304.pdf diff --git a/audits/088_timeBased_certik_20240117.pdf b/audits/088_timeBased_certik_20240117.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2edc369c3b097b9a044ee5cc1af98a48a11a4aa8 GIT binary patch literal 1678043 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

;fDYA!US;}mMV#Mq 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%0Ay|TpZaE9N}^Ku^lzV#$O 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

KxGi-T_IKRy3aT6 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�rRJdlKg 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

s%@4`rytzQvVddY@mzCuYFfr)0SQ;phYg+dG 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 z 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%0Dy1XB9*DLIsdc&N^<6~n8E+yX*_Zik(T{*Cq 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

O(2_Bxmef#mJpMLq% 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
    -yin+t~WuP54T9y9`Cr=oY0U^HZ|7<+Mk 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 z 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 RpvR#%;UgbeW4$#e{D1rzEX4o- literal 0 HcmV?d00001 diff --git a/audits/094_timeBased_fairyproof_20240304.pdf b/audits/094_timeBased_fairyproof_20240304.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ed44b7dba3de8024b9fa6fcfd2c5c350817356da GIT binary patch literal 377114 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 ~ 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 ~j-q2nZZDVvhN=XA)*MjA=*L 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 Date: Tue, 19 Mar 2024 16:14:58 +0100 Subject: [PATCH 20/22] docs: add the quantstamp audit report for the time-based contracts --- audits/089_timeBased_quantstamp_20240319.pdf | Bin 0 -> 1274136 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 audits/089_timeBased_quantstamp_20240319.pdf diff --git a/audits/089_timeBased_quantstamp_20240319.pdf b/audits/089_timeBased_quantstamp_20240319.pdf new file mode 100644 index 0000000000000000000000000000000000000000..82b77264440932bbd6a74131d26e6e0f6f730c68 GIT binary patch literal 1274136 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 k|HB-=yMOgq2NYadQUCw| literal 0 HcmV?d00001 From 0408defdd7abacdf440707465ec62125e79a2f93 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Fri, 5 Apr 2024 12:08:06 +0530 Subject: [PATCH 21/22] refactor: add isTimeBased return variable in vTokenMatedata struct and rename rate varibales in poollens --- contracts/Lens/PoolLens.sol | 12 +++++++----- tests/hardhat/Lens/PoolLens.ts | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/contracts/Lens/PoolLens.sol b/contracts/Lens/PoolLens.sol index d17ad2e1d..213968653 100644 --- a/contracts/Lens/PoolLens.sol +++ b/contracts/Lens/PoolLens.sol @@ -52,8 +52,8 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { struct VTokenMetadata { address vToken; uint256 exchangeRateCurrent; - uint256 supplyRatePerBlock; - uint256 borrowRatePerBlock; + uint256 supplyRatePerBlockOrTimestamp; + uint256 borrowRatePerBlockOrTimestamp; uint256 reserveFactorMantissa; uint256 supplyCaps; uint256 borrowCaps; @@ -67,6 +67,7 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { uint256 vTokenDecimals; uint256 underlyingDecimals; uint256 pausedActions; + bool isTimeBased; } /** @@ -399,8 +400,8 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { VTokenMetadata({ vToken: address(vToken), exchangeRateCurrent: exchangeRateCurrent, - supplyRatePerBlock: vToken.supplyRatePerBlock(), - borrowRatePerBlock: vToken.borrowRatePerBlock(), + supplyRatePerBlockOrTimestamp: vToken.supplyRatePerBlock(), + borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(), reserveFactorMantissa: vToken.reserveFactorMantissa(), supplyCaps: comptroller.supplyCaps(address(vToken)), borrowCaps: comptroller.borrowCaps(address(vToken)), @@ -413,7 +414,8 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { underlyingAssetAddress: underlyingAssetAddress, vTokenDecimals: vToken.decimals(), underlyingDecimals: underlyingDecimals, - pausedActions: pausedActions + pausedActions: pausedActions, + isTimeBased: vToken.isTimeBased() }); } diff --git a/tests/hardhat/Lens/PoolLens.ts b/tests/hardhat/Lens/PoolLens.ts index 9f62666f7..7e8a528f0 100644 --- a/tests/hardhat/Lens/PoolLens.ts +++ b/tests/hardhat/Lens/PoolLens.ts @@ -362,8 +362,8 @@ for (const isTimeBased of [false, true]) { const vTokenMetadataActualParsed = cullTuple(vTokenMetadataActual); expect(vTokenMetadataActualParsed["vToken"]).equal(vTokenAddressWBTC); expect(vTokenMetadataActualParsed["exchangeRateCurrent"]).equal(parseUnits("1", 18)); - expect(vTokenMetadataActualParsed["supplyRatePerBlock"]).equal("0"); - expect(vTokenMetadataActualParsed["borrowRatePerBlock"]).equal("0"); + expect(vTokenMetadataActualParsed["supplyRatePerBlockOrTimestamp"]).equal("0"); + expect(vTokenMetadataActualParsed["borrowRatePerBlockOrTimestamp"]).equal("0"); expect(vTokenMetadataActualParsed["reserveFactorMantissa"]).equal(parseUnits("0.3", 18)); expect(vTokenMetadataActualParsed["supplyCaps"]).equal("4000000000000000000000"); expect(vTokenMetadataActualParsed["borrowCaps"]).equal("2000000000000000000000"); From 1cd1a70cf58ab2c07e18641e952401bceaf54307 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Fri, 19 Apr 2024 16:25:30 +0530 Subject: [PATCH 22/22] feat: update solidity version and solidity-utilities package --- contracts/Rewards/RewardsDistributorStorage.sol | 2 +- contracts/Shortfall/ShortfallStorage.sol | 2 +- package.json | 2 +- yarn.lock | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/Rewards/RewardsDistributorStorage.sol b/contracts/Rewards/RewardsDistributorStorage.sol index c292c560b..90cd7904e 100644 --- a/contracts/Rewards/RewardsDistributorStorage.sol +++ b/contracts/Rewards/RewardsDistributorStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -pragma solidity 0.8.13; +pragma solidity 0.8.25; import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; diff --git a/contracts/Shortfall/ShortfallStorage.sol b/contracts/Shortfall/ShortfallStorage.sol index ee4822021..15e045ec7 100644 --- a/contracts/Shortfall/ShortfallStorage.sol +++ b/contracts/Shortfall/ShortfallStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -pragma solidity 0.8.13; +pragma solidity 0.8.25; import { VToken } from "../VToken.sol"; import { IRiskFund } from "../RiskFund/IRiskFund.sol"; diff --git a/package.json b/package.json index 179e0ad14..dcf048d96 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "@openzeppelin/contracts-upgradeable": "^4.8.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", "@solidity-parser/parser": "^0.13.2", - "@venusprotocol/solidity-utilities": "^1.3.0", + "@venusprotocol/solidity-utilities": "^2.0.0", "ethers": "^5.7.0", "hardhat-deploy": "^0.11.14", "module-alias": "^2.2.2" diff --git a/yarn.lock b/yarn.lock index be33df807..b29068d9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3171,7 +3171,7 @@ __metadata: "@venusprotocol/governance-contracts": 2.0.0 "@venusprotocol/oracle": 2.0.0 "@venusprotocol/protocol-reserve": 2.0.0 - "@venusprotocol/solidity-utilities": ^1.3.0 + "@venusprotocol/solidity-utilities": ^2.0.0 "@venusprotocol/venus-protocol": 8.0.0 bignumber.js: 9.0.0 chai: ^4.3.6

    *Mnyk5~rZ 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 %xx>DxZp}RWgI#^e+gsCq#L7B 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%0DT&${Z+uKD&<1 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%0Db_TtG-bKG zNw8UJ-G^cvF+F@$n$rlvEQbsM@jU;Jk780NCOts^cC}8(Y)ubChr-ex=mM#T3Om`% z);llO6=UJ&t=Ef1H$^!wt5O@iV~K1WOVLIuhD*j0Sw5g>)4J5y)VD5?8DlBh$YXKI zSbRHXoh%6(Id43H`c9cuYF_8pia-L5k-ziV5(w-v@_CcE0*$4EY)ihto+P+5A0bW{ zgJb8@z!ONDxy$yAGNex6`4IzvuVHj(3PX}Uu!bJimT>XN+N%0fWowlxShU8^tgVRm zI$2gIG6Ph?4sR zH&l$PRC^o7!U@08fF zSm6(iHnD<9xz5B)NasaO@@zabnVNGByLX!g)oVZo#D}JzO+mEtk+1W9tFvd~eVIVz zS)<|Z7UQnYyO3_Q+QHQW0Fg}P^;<}$RQB;$H7x;2U2d;huuCT-4xncEMp>qoK0}|A z*Z(LX>SRmfZSLuR054y!9{17lSH538{`HeO8{IH4$A>_^Lj?l6OqGa&Iw6||sh^mWF86xvi_&_GO!gU8yc}TE?hnNCS?n`6K=veky;=aVUPKYbI=nA znmL`pYHCS_VEPT;hy*$K^OGY3ZMZ_zcHmXvCgo&KuF$}}a+)TOQ|&!OY6N$}dIkE( zu}+Awpy^>S{iLx($YB#&Bcn+$7F~~wl{7HN)|tG?W>a6|BTUpIy;`N$uLTn9@*5sa zUIkT%*?Ov55hfs*NI__EZ%4;p`32)~N{_$t%UAf<7~aHyP0vn*HkS0eG|&clpwa>( z69$awWBj2flMFn4j7upTU*KM^|2l$$MfW-0Jmq31cFF*heDEn6J_!fn#LH6c>G zny|xTq&MjF7y^hIZ6;lW=m!G(G$t@^Mw=sjcDE=%xQp@#eRHSOG& z%V4}M(_RYUkf&uT50>+=Q&3dK%`!xc*wH2@MtHrqhU5UjF3er)hKLbMG3MorzTc}* z^Me!e%ONgob*Hjx?m@DW2UMCoEDG{UF=Vu_wNwYsZ;{xz(&BNhpDq4!YIZVsTp_9r zH%TwirDud{Qh$g(INffAJ)nu#>PlP+xNz?(N!gRc3`fu z=orycM_Y3dq1)chq5-i2qy+{R!-zzs)Ew(RO_WBq3}AUZjIOO>zLhYai+?DsF33}b ziWsWnp-}4Tm8^@jEQhN%FU8-}Go>5G2Gr=DL8E&JP0N;)>0#x1K9*pck4R2UbI*%_ zHoHi6=$5CeHaRsi75NI)DKI+UQ80_f!fRa=s@f%ojHVv(KXnJAt5I#{BcnhYm?9?W zh+qrqCL@K+J+JNa^{fu$%6UpgsxhjNQYn~p{5p9)Mr6^^=5L>4GhCJ>3mXwxbhJ$4 z+4ZE#TlC_N5gBUV&OfvW6SB3kGOa=G4N=Gcty6&P-J_|}IiK(e>#z_&13 zHajxI_?p+n#2k3q-7RU}_mLSU5ZGnTGxN|BhyV^*HPV-75u0V6kLn@j; zAby?P%xnoc0`H>gcbHsq!YCr;#uA+NcdP0Mw+Y75C(u9n*EvZ2a<@zWMPl2EO*Mb4JnlAQ$O&G^+_rJ#M!~4ymL{W z@&2AiHU%CMNLhFtX;0wwls@34rmyD#Kwv=W89Hf|Pis#{2hI z#Hk#SRg!jU$Sl#9cy_`xK($Y;t2p5 zPo_}MwDwgYB2OyWZ2;4+ugz#%OAP0566k2?$$mzg7n;=06>UrdGPDI_=@aN90~v0LioBmbX)F;yAY4N4Wk~+!j|Jy(c3nb_BGP>w0^Mg@ zjIbvOsu(4%A{b@`QaJe|?4q*6*75{OT-E>%9>#(TPJJ;HOU=ElSe7?_7Ttj#G7(UK1bFpe_k+<^t?ppKcWW?Ep7nz z!E#8s03wFuC|oZpFL&NeaJ^2CC4vB(cNU3q{K@MR$QK-MwUAktZa|fx)7f?%{IPTqh_@|0mT$B+9${(Z^=hqm6r3VIZf()@Tsh#Ib(^-iUtG?im{5HJ{d)n8MV!-! z_bJY4UX=2oK3Y{+3*d;F98H*zctG9b{u3>*sQNR2LwCHH0=bL2d2X3>o58-nBi|pj zd0I&6Hp@S8`)O7bnVDSelnKvjXOzA2Zn=p_9~21e+JC%w-UuzPZ-{AjP>{0bDdgwv z{ygkxQ2e*JblDXx5a-q!r(@hmI0p$X&(-PD6WgH|Z zw+zvtZ&UciM!qOoT3)oBC7<2B;>QZ$rJMFQ^Lj^qIi0#V?5I;-#0I?MA&<88c{}NC zIe(c1kY}snHrlG1y78phDZ@Z%XC_Na@;@fXM_r>}xYRzEOpn^schUviDROLs^>JtAGPd|}pN>7;h$|ZX@3tK#FR~~!BR9;ML5YR}= ziwl^!xOYh%Zv7=rBN(w1Tr!{a&PWknJux0ya~1Z0F*xu1mf38^NNAM6=+rv zVcmhiE)N)^nJdun0}y=e3q1I@sq-)5@{z?;&KA{~g>8pGpdMm5fj(HQbRRVW*?0&9 z@=2W4(ul=JN2L+S+ddH3<=TlTe&pLT0(svD0{QSwk1)CfAa4!LEK33Yc4Z&GN0|_* zqFp@}#3B1*=@jT=3PoS4r=z}XcPT%3S!#5&200wAZk1i*f+w+ zV6acMh>Q0H!jYBLyeRDpgO=(=n)n7rk6z{For9HSf^hIm?iD4p-oPK z*hhDSh!W2WELh_R91z2xfQ+a(Um*PM={5AxgR->2A|z*;-UKAjnObhf#owdkhLks> ztP=UOSgi{nolUkg)R7}Tm>0RIjij+WRP@w!>Q!(A&M_=Z|O z$laIbL;sbwe7^0R<7i%Dqg;qY*_UA)_u{j~Co>b662$rEChwrp(FGkWzVbl^atF`J zYGAwn{)J>E`Z$DvJQMMNmpy8?ULY_qu2eUY#Qc$8*!&D^2w@ZkuReD5s$76LZKFMr;h^l zuL$XV{HrVwYg@WIr4euZHsTwh41vHdLp92GNIY6mX+E2aN*}1Ddx-|s+%6F_kO;NX zHg^^C1f?!bHvLQ7i`NrG&pq;%gm}BYHluBAGy5PE*q?MvPI{H2^W7EzL@4m1Kvg>A z?s)vG47|&r3K)Yc#rM>E0HF}Rz%H^f(DC&ml0b15fx$_qj|OXwNd6~Vicg8B+7}rM z5`0UcnkS3`ub*ijy5n|S4=|p1Sp>ZkH#Hg~bKAtBGFIWKa;`k@XK)FifXI495ij(( zqKAUT2DB_kQr}1B8@fZ})8`NvU%y2W(gGu^z%nZkofwY4aXCL~)nslgW5g*OY{4+Z zv^;i4biQXtk8BQl6E0B_BVLrHX*MUG>y&Rotdv=T(R{>nbzhsl2|@P`yu45#@3}{h z_=G3>DcbiVPBg0R)!inW&fa`VZmSUlkFK$^74Eeu!S57)(%;W$-wPdUgd?V}pGEWB ze#%7-?t;EHqx~s$WX38p7%o3gDV(^myzVDmDM8o;$DGi>S)dED2SRkLil2{es{QfU4iE1 z6|p~$0uLRIafoR6<;YB{RAhbFx*iDjcb!F?cp(CI_b%hOO{%0 zzN}F49(PJ-Vv3Y~c%PImJb^C!Lcieyw|w9YSU&L9FCQ3m%7-#F>{UKH(p=hzad?v= zSyX7Pv{;(vnJnv-Z92Gf+$3&*!b{LJC7jR?GBQfwufLIzQ6-h~8!P@dUw`wb_l?9q zklrAs$m;*Cb(f4FO5l;Q)Us@_%XDamjNszT&(obqgoTU{dFx}6}Y2x>DrFv?Y z^mCF%ML@+)*pU(;u!+s7|^%G~w2+FePXR@D>bH`F%5KzgR`;ihTyCQqWGMn0g zYO2XtCi}1=8h7q44kD%bqW$a&H0&;fSq3A-uanoOh($_eT|}MqtkblmBe=$8=a*_F zl=rxaFl}BT zhS+`|`vgX*B&q798DUIw>=jrRNA$8?z+*lOc$8WOH0S#pG6{$A{)X62)WLhQhR0a5 zRXb$fAVLALXeL5XT{mxC^8^Q(n9mjDijs)*0J-@@Z+V-)HB);xU0If?=up4yt)*3Rn#0KuJz3ZI#Lb3w$QE@3)VWvBDf(h@HtY3bZ4aJ zHyDJSZ(!#8-Zgj+xZRTLbCuy$JdoKVEK2lxLmk<3JZzPOiQG1;fTMIjEBo1) zC6<#zPZmx1=}PQ7@_c$nm*wRQ1A8gL^YX}BoI!Uen=91ZGs*4Q9x1=sBrOB%L|3S8 zRdEnZNXJVr$%shMLwZ6i-|H^fLwb_zlfmhGwuasZU&Bs3!dRXh(i6udxPyD}H8ssR zL96tPR#0vf)>5pOW3NO=gaYEN(xgVX9D+G*?`mz&R(nL;GI%i?8JUgMM zI^(h5&&y8eWk$AB%6!Hi1UaD<`I?>%Fj7Q={C-||LQC4qsmjcpozFV-BJAg7Cp0Md zQU8j%uDzb2s#trJ>kU^K1IPH67CcS75g zH^Z%IXbD=Sm$8C!b68r&?r>|Gl)XYL6t_Yjth=VepjT)`CTJg8gFT^(zx%jH4{wMn zSRC#7i}X~-&~!-V6xnx-Jhv*aEVT&?m_}4UT1RVDuRLq7Q-vsqg$gMl`+3Zn8I0jD% z_UJ02Ux*n_!eLH#D1=@^gxjMFnRY1VcnP~Y-JuGW&63%0gFU*IYKLNugz&zz9g0$k z-z4$MR7Fiwu1q2Lq|BEn;^+q2u?}T#8i&0yD;PHOYdI!++crdCKza)OYd^W3jjv&g zj(44iEwUYtFEo3NxQlEo4Pq}|?^WuxL}^r6vU{7ZK(kr|YT6h)TcqT2eBjY0$3R8k zh&voaflpPY?B3z{Mq_zes97i5GgRB2;qcxxb$fdqK_AFZ_o=D~(A#tbVm86u{!HQb zNZ~(40fIoL^>(voPusFbv{82F2a!&s8HVt+MaK)SzleEC%k&YBWEy|p)=hYVJIIrx##=}SIld5`hQ}8!+|)sY(6T>}ST5YvL5vWIG#ZbvtKea^cWEN% zdLXb|xvzcfqGJoMsx#->BF59KDN$!li8^Zt?W`fRvxd;lX9(>%1+CnMQxMxjvu$i} z&I5DK|0Kfh83Y0%3$g4M2^jiL`EoP zvjQQ@=tUwU6hk(pW0a9i{|U!Kkb{2NZPq!Yt-ffK(NzxFc#lzDh_pd=`enDtE0KQu zqEY%7L?VqfgVKZ7hzvqsNTdOGWOcttq;EmZcUwpvnd>hS>7x&cG}Z+w4O}GBN1yqz zP{V~bRFJ=(*3uY?OY63G!g=ae6J)R_k><2oE<~R?4#ilCsB)`NutZkbCjcG?RCyM- zE#QheCKstsWC7VktEkm-k;n*rkSF|@*bA?3bwG$&OPiG%HFvHVWspRl_9eSdk5NWW z!B0@1Ajv+7wEObH8(a{ivFyl@t)pBc^f|t8Ayx!29MmV{0a-7^iXc9NL>fQedLdQ> zaT_Gk95w5OmI{ZCy@scmYAn=#?)AbuVGv6}B8{c8UWpYxJdsFasjL^?34=Ha5@|N> zdLdSDEe3Zj&4IdJh!u4JMFqk%O0zGw2rE7T5u*hDH=J&C$1VmNU$*7yIaf*5C%Ajb zZQM-QjN9t#xuhgUtTA+*Eh@!QB#+WuMLDFU_!lse!b(C?*vVaP&*c)s*XVM%qs~TJ zicc9>cGSjIyhdjK;H0D;l)k248iVxxB-0#~s26aR%*gJsg?dpk;VPLvvd}mU*#JrH zW0}hR$QaHuhpD{QO_FIadukmMw4Qx3{figLG@y+dAXkmkzj={6%YX|K=EpJ_1(L5` zb5Iq4WSUcdYS}h4w|z1r&yP**JGG3PZkZACNFj<@%L30;S>OqYoSuOvyqvEUl>DKf z8O)jvaYpu-atctbR7TY2jr;B#Y8;q3%8bvJG;mn5X(upsHzqpn-L;$_5#n(Enaj-FMI?b zACoyPk%B%#I*cWILSsCyHz~<91}f@*TqU!zM1Db2`Rlj;`IS^w`o+7C-+lPL{P*Ae z@#DuIe)`9^Z~yS!$3On%n>X)1{Q2$we*gVne)`pqA3lC~_u)@(|GWIxKm4HoNniN$ zcOT#G6ecpg|N6e(rs3WD{hN^kN%(l4gJ|Kf|cmZSWyFVowv z-oN|!+hN__%r9i>P+}88q>2867V*t;&%`Q0Pu&?cXC(6a$1}=XiKZrH3-D$TnU~Gz z(-|V=DVbm>t!?3oQ#Fe>+nSpq9|CE+2^$0HYL8upq_t1>x>8J@?e&_ZUSC!Qys!}d z7MLqGJ<{l&y})ta-s|aJ_*gpM5sO7a|Kp$k?O$kaUyu6Wk5CU)TuMuV0ua=SaV(6j zTYk69GHF+9=3Ck8_ixAHoAvhooBJ~U{+nTWPye~B?u=|6c(-ih*V{M0-=1qS z>#pwgX(P2xDKhJ+x7TffSrnXz_qv)qxmB!ew$HfN=aP2u*z3!dg+sPxoGFs3BVC&-k>z<|OSqdm=P%6JiZ! zPXr#1GwpZFhDK$QP%~kHW@Xld^2;<+_xk?s_wT>?dL6d+%l7rxE7g2_M-I{X9T6qQ z_4hlS^xN=$qWkuvnty)LA2*^EA) zp>3m+T=)8NE2n&JiYl--M=K~AwAa~fb?!0%UwfDFKOq%-w%3D_9Au>Mot=cU>x%X| zShr^{*s1meanil0(Ai9ZCBUPaOt|lGtxWH`%AU3|jfVs!bFPwEA?szDse66;cK!DK zH{ZTnsLT)@@bh#Z*7q}&A)eNS?DzNYfB%j=6Z_Zye|zV)V^?yV>3aeF4uu{VR$XI? zu-FgJK)mb4A>a8u_2PXwi}~xkhj)(NJ4+4;s*hdlL!MJ=-_O#%hsT`0uWwEg6Mw#;LOx(a-?%;>vg9Kjd}@jxUlC&KKSt;WME`fa7@@@X z)r-k?JX68EvSjtG`S@dM`(qdPdoCj|A!pgR!?R-VU)*n;m5+)iXK$gP%Ky)7+>=+& zzq)>X`{>S#=g+@-^=6Sje#rZJo9*Mr`}NKB&FcCgFTmV9zS&;J;vj&-M9X{gAU9KKts7 z)3}dy*vIkC$(44Dj}NCYZx`6%<&F<5u;FGijXt!@-}5#KHhc^Yd(7A{u;GWdE#CHG zJkRm3-&Zf*=RD7g0lysp_jo+^(aZdOyX(9f@bG%xd#B~$NbaM*nN8t1)Zg2*e6!4# z*PENii<{;3?e%W6y}5mSNfv&yT|9nBjQ;51&EnzZ_GZ7l`S3IzbC+d4fH-)Q=wnmL zW1^m#$@4POZ-*2<9(R7MN~aeszBiSAP({4gdvMrSXItJx`N-_Wdv0iOm2X!2^sUD1 zaEtPzkCvv-uS^UmpPX&J--@Ze}ZKq4# zqx$FTr?=(-cPQ?~TULI!KVKeB1tvsNP3%k~oS0Hqp^hzZN?k)e9CuHtm!S@0J*8fS z>Mju1Kpp2`6N;I$_4?a`!1h=>iU z+a;!gI->Z=*T?~&UymCJ9;nss7@=Xv-nEdFA-o#Rq=V6~+D*b1s$^SnzyMWaoWmoi z)$SO1$+qGJGDb)vpQC1|ZkNMgsFE$WEmoI@XD24IaUlY#zqUf+%foXc6JFNf>hb^{ zKc(`u%LADGgi0wYRQH!^QK;4#1)Wf>Gioj=kkNeL{jpH3Gb$IMS_%RXAbQM8!sE^B zkdywB^90jszLVrp!8fmRPFYde`tShbgi7rJr||9q&(W_qCsn%}gjgP`1E(z@1WzD~ zm)l26ui_PDGrQ^m%XNDw_?t9JnaZY=h_ke*`HVNy6PFu-m);+F3;Fy2zdPA=S1k48 zd$E(RQ+Np=nIs}2TOEq6rkq#j>zdvauk#+Gf4)6GzSTSZIU`kbn+oj9!$U+9PPUE% z4Cb`+**U!Zt$5>;MWC+(6|+1%c{^?M@_c!CNMK65I$s{_;gpC(2bA6^aeIDscr$29 z+?^jQNvA|in+I;q_C)$Xb8O8=e~|HbGL( zZWECX=s?ppH%Q;Cth?ib+EZR;)Y_Y9UMXV>($>1pc6ofxdD6lPvDSyH!c!`J^Uc(dytu9#1Gk!|4(jdy6Fdh6s- zV5qh+7$~Tv2ZD9xj%6cF$hmA$Sy$fG)>zNw;k~g*Z*g~*_Pf?Rq`R~huP{fvLNQm@ z73S#pSjxLLgC4y1QoX_)?G7)TOgJ$|%Y~h*E9?>Ipwjjg28o%kQM|$;kwn&9Hs5+QEt%I?k;257ai{maV*Jfos^14Og5H@Rn_G8K!JX3Go&bA>sliNDX1 zTpUs`?^L$O;{s<~6Q6mJVU%b=9SH>ZEXLa7hS7kGfV9k@jscp_NT^8Rxd#;~7IMI$juDzKHK-XO ztstmlgsfj+gW#Qy=H?Q6zzDf#nS2YmnS%|`bMR`tLPZL%SExwAiI!#`&r>Zi2&QI6l^(be!Pn+1 zi*_@k6xu?~j5<8~IFTazHWv-`HNqa+bsvaC_D$Td$hsbsMZ5B9I9nwhC{V%Ao4)9Z1^^-1C-6XXk*;@d2_XIqF-h>RQET& z&GFLTgg3s;@!H;$iWG+%RnxEG+d#F>SR=Gx*^(MK-p`x1i)Fs_dfJm3KsK$@{m2a* z9z&nBKvgol+I9C_ihydZgPsD_J!ADjwbsc3K(*F^34!Vv#cd$sR?jF>22kCzr1+?? z*9yWRgX*4*EkM2>yH9#1n-4WTvsK$C^1qay1#kKwX9Q}rRA7cXO%yosl0~M1N z=A#KUvMD%+I%J#o7wV90-Uq1hLZuz3$aX}vemkq7BHQt)i77R*DZYg_vK`>CCcMP` zP~C?F{>MkAro70umM5@XjL=`}7%H-@^}H`y_$8MnjB5fkksdN@8KF{NfsD%zoi%t?h?P&01I zc5N5KI_Y2lYWk}^6>9pcSQu*ht9>16`g^#{J?ZaA<0@qYZ^lBt8aIQOJ8SLAxi6Fv z@)*aGt>v@AOMj0qSWfy7OLlzDa!SqI(Y`|qnLFBdppLmS-zTAtxihzK+ePB>wY+qw z@sMTxp~f$&af@HKtCf|2e5d>YE#MjLYJ`&H-j*g~$q1ll`xz}T*BA01wghZYvRW(DOHk+OOcuA z$~8k};v9hhCsTwQu~0qiF|bF7z$q^i=ZF_Lr804j;DJ*r193zWoKhKxjqr>x`jlG*9y^0B*&GBgPK{Q7#wQ) z;I+xo2~-;kp6P*V2ZpNs@LCVUXxgpeL@T`3!!VC_c9z3D+R;dP27T}dCD2>jSfsWL zUeCU9u4@yJLUvlHcB36-1E|RveXtZUZfiSHxoAoY)=ok?PJ=X>Iqu~&$kZ`+JRcJN zaq?zf#%*QygCtL==8Yv=+4)_@lC5mym$76kyH?BCEY1YghXjS3Dw>)ZW%mwuB2;T9 zc4%#vB4wON;SowuxKiqni(~YR6Ik^jp`y=@;f>B58Z2XnR!SXimkA12N?$^acI-BC zP!Oue7~A4gdKzFb*{9Uqn3k2|Xn0YXkMy^r$ix{gs3_9KOi&|)4cRC?DR&7U4qh*S zQIN7yfd}m(1-N)~DMpzJrx2!QN_rWigY-`*!T3Z7OEJ!9ZO}>8hS##ih~QmG;$be7#o3~m@LIM+UMssWbTz#0Zwv!hqV=`J zWB6yLW}+$=wZ)-;YWD%dA6{!R<^q4x?M7#I6o}ix>(NY%<+6+|3J=w?#V}A3tFI+O zBE>3dOaNY{snLVY8%MdJ`fD)^c$sb?BV-4J&xhADD!D#_W4Dn0+8m>glZ{-4D`woRA zP;KV%_|k&b#i;aI+W3!3A3Tfse84+Q3)W<;2-lg-oBleGNKFq^&2_xwP%T?*i;vBy zEsqp-5s3>z)p}dUw%`M+XUXc3U@|rRwPhf}f@;rZ)aj6RatrC1&JDKfoKLxEZcDXh zzUHxr#lcrqy9rRhn=*Cu*K?9{S$M03XwrTZ`H1jZXR%Ir(fV4ldK}D}nx5GUTE{vq zo#P@753jWzJA~Koc8AWa-&mYVeywA1miA%Ru{f@C-I8kw)iZTesoFOp&jGLPF*%WZ z%{`07aSh~_98Rc~IAP1uwtJnh#id2GkkPc|T@Q<6JHMvl2wsm{>=045^qXLYC|lH6 z9G4<)N#%y>SrUum`cQb2qqQYl$KsIj@Ym=s;Buy>zqT!;v_rKNu|woy)WRrnwdGyM zI+6J?Z?tYZ#F0#>)?{p!YksyI$%N|po5+VpM&@6;jLjlbWooo;d(5FjTG0N$p+k73 zGY%cXtNval9&+W!_HtM<+rrDlL*(Y%vy6o;B()KtYAiSiOCO4gY_6f%rk)9^#v=7h zP_3O&GxbbRs}C6=+vC(TLA53mQMuk`n|dZ>vvy(&T^R=N7&l9iw45u9 z;N_fy16gT37Sgpj@J2T8%BgaKS}jC2TM>@)LiL=C-Q-L_eZX$gGfSL$CSJ@mFKd2Z znvC6C*amPE9A51N90kK`|A9l_P_4;CY75(;)H6Y~Y_X;st*F1TrmjZXa(WV~*HEnK z!q$}Hm{6_tR5|egr@uC2t9FNMo_(>r3;UiF$AoGrk}%{TU0+MI$Pu2YkULx27q-&eH44@1EeCBJHmhf`{tL(cl&gel zO~(3j1nm|gn`3m!RYLVFNff%U<>kIpsMb2w#pul1iBGU_{){4)P_3Q#1QZFVzllO! z;k@M@RjAfZe1e57Iya_5b-S_t6jtbKiA`NOz2*EcRO@$GfBPDgTZPy2Z1@EBKq$9@ z*QsJkzCu;cDESIieW2tkRE-;m@}X+vDLZ2~vOT8kEPIs3jdR~nHA0;GhAK^R?wfY& zYaCTm$TZh4=f0t8hvD2eRLv;PeW7|?a8ol>YX|F33q?(Ty#lyN2-W@>KnrQXdcgWa zwZy4rcJ1eu+l)}XhJfaTYAelq1EG2}hxPZt;1$*%UXL->AFB0>^`{R-jcm?_a^Wp4 zST?LbyhV*{wuM)zaps9Ijq&gaYzw*Nn-)AvQscb02LkL_crEep6l~|Y-5Orc9Xti7 zo@aOpq+zUeJO!xk8J+?ycs}4M!0VpjDL}Q>QxCnjw*sn8sMWJEZbgl3wijT^K(!s> z_Hf$uSl}tZThz#AdwiA38=e8sXr}Up*DpOSBTK()^B324`=5TAflTeXn>+8zUHkrq7ixr4N~mChw3QiH{tv9R4t**jFv2l50^ zJwkX2P(8-EhqS9b6;FYbW3`KHJI6!0heW&XFP;Lt9w9shsMUudo98;&19&Y3{sUBN z9shx3sK*We0p6l!-0YcyC>Cn98` z{sUBLaufeyXB)eT|FE-H0h(c`)dI5Z>_2ScKkS^R-HJ_9`~< zA9nUCHe?!TK_kD3SF!VY+mLC1syVrdud%aj*^p^q9czR(@ilg~{+sw3J6nJ52B%%k zolSg=ooy`mkWjrxZQ@nzyhm-~KkU3mZQ?(GfHU9EHt`>J-aR+DBekJ_G~usA9jx4 zHt`>JwoV{=LbaXe%3FA?$@mXDTQaV1r3J6I_zyeV%}xA=o$WDKltT5&N~Xc62q2I~ zHlJa06);qfQ2d9T%i6dK2-R^cR{=xyTpyLY_RP5o2(LW_t^%fo>O*9+uK_+&c&)Se z4?BChoA?hqdp4W+4?9QAoA?jDK4xRL>n^f2bNEE|#QHUaN&G8SvV3<@({(%A))|ywVP3=HV@BwC>oH>S*p}dc{%|99~Hba9XIAI97UVYf8OmsG21p zFNbRF#7Y~jgYO^(hG1@;sG@_{Hj84lP_4<>V|EF(5PJ-aoT-t*o&qIHp~}uvM3kO+ zgkq()wuKa!gjy{ODXiaE>8))c#S)=v2j9j@Z*5IEUQf^bwb)~F9+Eircxx-dA#11} zq1fYX&D7ZAZOzHp<895p*kg>c`Vh;zwe8-<@@{RVN%Dtkt;h0`^>e#Jiu&4+!t*zl z7so&?#Kv;oW@@zFyh94>H#Qbg+`^E;`i+g9chBUm^{CREKyuADJK_BC*7!Yl3IZiT9uin|r6w8I6rP&HF`!^YaHz~xIHq%$tg zg(^MZ2!<*>>|%L&(tfTTF62SAC$@`?#qlyP{l)Pz6|LiVnabQTMjLouLkeprHrA+G zc+}~yb5{iIp<0u}#yW#Rz#LxdES7g;pO$bJs?X60VMDbhV`De=qX?!#wRVP$wJ%42 z1h4%EAk0FwCSzm4v6X&fV|kmx)FFkn6B|q5Al^i`1VyGs>-H1~-9oh{V`Blaa0^2U z>nzdj#(orGG*tTp1k9m&_Ql46!=bMwjwLuWbx2{I#l{jGninam_JBYfUfWGl1W;|W zNNI$(z7{ELv$!N0su78^@?#MEfr)`=8MsKpztJ8wjCC{&M7Y%FOae=Snj zb_0@z&T5txE4`&izpdE!t7UfWF$RYKJWafv)s?OZ?==4;X~ zM=haBzZ}biYW>E>0#_uhC%Of%$W*ire4MF63XerBFYs~Z9a316vAk7(7F;39*QFYUU_xr<#MRjZ|pILobDM?R6Sze zc<1tjTSx|(BVe@<%WKeWT>Bw~M<|xpNLBC-DLj8;kExpiUFYdjAX$Te*RL|eoV*{%bET+HqjVPlE)pI@3tud!*VMt+3Qh&zRJW~_%Qi7v3 z6w7O1b=pmT?FCVq8tPnU1h+$qxz?c$DdswZI;5D-5~%5~VsxnKulyaT(Ym}rsF6b6 zAk;`9ZxHH`Vy-hz7}8&PHc-=Fc{Wg^b@_czhZJ-DLLE|AXT$Q!?}In}l@9|o{gn?x z@*rB5hX-{?Vf`lNHQWlkkwP9GRQhYQH>hacXm3!_x)JA~4k@hPVR@CoAlWgbu+9?Q z8n_-_`fK2NsA&CCUK`XQh38~qUc;{9Dq8cuznNs8byv|(vZSBi;ea32Joi8@-?7F>+-~) z4k@hP*w{;XV(>-^d155A(qDNMP}5&|6;Pvf`CL$k6xMHSte<&+cSvEKCAu|;5WMNH zvK>&Pb$M4i9M@2--`H5=9l|@Lu+DNGYeY(T(_dvfphoNRqo76#`B6|Kg|Zz`hZNRX ztf`SXNiL?psy%=jt;=JAI;60EV`GiX3Ga}?I*TMo@gy&H|=HyG2cZ<=N0ew63fV z)FFkeG!bZcr5!GqK~>g=7Sdm3eMl9jzw&ILM(gryphgO1zn~5&q@BPfaUF8*k;0q) zD!&6YTG#0V)FFj+78?tY^vpLRwLPTJ>ldVPoyt1U3oYx#vh9 zB85Ghz$S5p)V#5#Mwz58BwDv;!qd|&jzIE zP_5r#W9`}S{qTBD#+t5`apCZR{u=2LDs#u!h)~hGaTK8rDXg8?Sb*|1OJYrpn8;BF z{WW4DRJ6WU#s%t-!a9qMUE8xE@(R^Di;XodA??!Nwem1f(YjF^sXrQ0c&5h2a`{#g z$Hp2@k`^L`{TX5=C6dP+SQf?CuDXibvSl>d0 zH(FO725PjfJPgz!g=LG4HFO@lLkjCRHkQlS(nI1{wq{eKb>(4rBO_W@9tLWpu*XEb zUa0fP65dE*kBJ&msLE2oJ63@E8yjmtJr3ofb=`=7I;8L#ijCzOz9dc@%QbvchZJ4` zvAl%&=8e`>UqTLzRBPF-XtcZsJ%!1;$H2(Yh)np$;iDLSQt6S0e;o zMyS?rEU$5mIi$@Buyq1C2VVOnApL~uv54h05F+hH3VULpIYCuE3SOk}eSfIwue}vO zm(s4sB9<2bk@=hi1}RjJMJ%s@5IL3}QdpCTZjCtrZ?tY72H>YqtA!zj$0C;3aD!Bh zM+*CLKu3k@Ssi<9+yh#O*6rB<8Ww7`5Gm~80R)z>S-**H4L8W~{E))>jXgI01H93? z{T&`O3bk4oQh2V%@*0ehc83(!@36=A`+x^a&&)e4uWbNuW_-me=rz6mcMh!6Ts}g~21Cjuqfp9n0%CkKkqQ7)lXpq;Q4^ zwtUSiATh52At^5zQdqyS$HrZRm;M^q6)IXcge%k`g;zi`!hDU2QoHT|`3l;`?rS7QN!Y^d7p zgU%?rq_B2kkB#-W!|3K~9-&xXBR9f3 zr0@vE^7_3yc!w0$Z|t#=8{tI?$n%{G=L25*MnU+3>Jf_NHHs#sUy;I|BTiVT^6+rN zpxSf92}{rFYtgzrro664yB?ufUL!(Mem11=2qh9Wf+f5|3eVrzV-|*V7Rzg#NLq;2 zo#(jAyU|%400G>vwjl^ z8(WhWh7{Is>@lW6I*a8st|hmkqIG+Ygs`D{EMj?aquuV1!gD9~7?W<^^w(Ym&x(X< zoej%tA2E1h@LIN5UIGVwEs-z|nyKlpy&zH=X}4O4*6kw(PYkNHJ}j?ugCu;yYfUB+ z#(h=KhUIm>geTQ#!I?4=U!i&|hUK-7Na8EJ)^98?;pMy!K^dcG+WUehhWnrvf+q&G zT8P$F<;8utA%*lCJTdy95el9dRB4CgW_l(~204tcxrJC>(hZVr#JtX`jh7IC3^4DI zLi!yqAp-SaUZfzzHZ}cKbrZJ*(K=}t@s5~RRbJdpj1o=B{RJQs%EU!IB4qf53=g6TeRNa{3wsy2`--u)8e9a>i%S%e%eHc=BgofpH&M^pI zv|#;?9JI4)9IU5j9-$HQI;$2eFL=EIhUK;A$iaGet=~k#lmke%*yAz*qm-&di#axE z7d7|{g<;^JBAS8ZpfaKScsEo;GcX%e2FRduP!Y{=ZBP--PcU&00MQKB29*IaTpQFO zg$F)H+E8@xMv5BD7-<94!5b;;o(15Gvl1`v7->VsanV0g*s%$e7gR0H0p(>7H(H1k z-sA?9m*M5$O@BQfs2&PclW%}_*+vh{E+epkKoF(dle>zIHnJPM84CM%SBZ{|4F@kn zQT-xWZS)g3BbfcppnDl=1=fs%6LnWH+Y7t10rxW63&;wQ%YI<6y{P-1FTX2{wlSvo zJp$MjpnfooY7?S<5LQj3D{Ql&+kkMOr}mvFjHFTfkOPy;XpJb2{U~(CO5#Dsx zem4c8X~8PM1{*vM7>cOSX+|nRL)9w1iU~HX9WA80b}R?XmO=F3&HT389Y8G#FEwD; zS_83i+lQBYbxQyu<89ZNs$hs-w%A$2qVn@CMD5lTL7yA)4cL&pIP5mDriOuolYZI< z3I>*8@8G0M_75oohv;1ZLuw>Eex7M*)nPD=Gsu-F`e|2ynsA=;6fRA4o>>%{XO_khLVGm ze%kZ~{mJlhaMDlbP=fu$8`<+MC?HS9zXZRCe%fva_{pe`aH3C}?Z7@6qY};xvDSOw zos8WE(h{n3N|D=(aLNk}wv(ai_<8gxD;5kVL(;)XKb@5df|Eh<;H00?Tq>c zXOygMEr3eKe1kKZ_d3Ez83zu|XkIP~_otEFoyT$+*p0ifk;t9LoEhv5&Pe3WW6lf! z2WKR5=ZXBd@2Z^v8@IF74hqxGNfPeML-brC>@z$ifObe^pCPzRhQNUni5!!2Ri2-_ z^B6uhJawLckDI|JB9TpGaGDH=$NxqmXFE2SNJH|$i9|J;m`F6OuVW&a<0c}J%`SKe zC`7gxxP)^9wefW%vd02E1VpX4z&jbG4Fw^Q{iT3A8KVtOBy#E{&`!p9gA<9Iy5XT; zB$7gc;AFrweop6YVT0;KTs~J_K%I=1#^j*$HoJjzGTIuPbl%Ah9ec8ZMFbk3`OF0to}BRfjF+3`bqU7E=gdA`&^M1r7#IE!Y4) z87+@4WsJ0rK+1ureJN;92JvH`ibU2YR@=~2a3YbtARvV3r!|i$ryf;eV#*CwNt;OI zARG7~IIHtWWbXnHB{^l{W`a1TVvNjVVk(G>nr(n;VSLenoW8+35n{u$FXw#i1 z;N%jF+l)l+JQ-gunus%=fFp50x8U@wBM7B--#yf}Q9J<$_P85xTB3LYc6hKwaC(UG1i0ZS*)jSCki$B%-tERPy!_k} zVf2k?h{+$M`);H_exA--BBEX655mcC*f|-nPbDT++c0>zHFU`q zmKnzm=C5O*jdsV+>5`oj=24)J=VCGq&q2X65hdG5u?XmrW-`kK&LW~@TWz)qI5oZ5 z72wn!!Uh1R<~(a1PPwnFb%>S-t8JJ*Tu&tOnMm-U4D$yk64}aNA|U$fSZ!m_@pB}y z;bV`7vwn_5Hm2;{aB9x8bHiyRW3_oFNdt$~Hc%Z7dd5i88>e4HQL%9)2 z?%XI~goSk8MhZ`j4_Whs)dqj#=jpsPPgsp>s4ii4jY-GPk;u*o4k<*7Nvw?%sWvgY z#>4}+JQ7*Sm|bJ)!MR2uo^?d!#({$~5?RSa<;IbN6Nzjh2^t`JXTTO4E{-r8iR>N_ zgh8}EvBk#0idx)M47--|vkt0|_ z^aR5|8|MyA#>n;^9}c2-o1C&XC;hZFB>0BtamVZ$F^&ucU2<5>;)G}|VPOqq$Iqir zi;0CbU>%(F)AoHJM3tCC&_*qRknPw+B;Cvz ziPZT(M;XVCE=3}D9s_M`JBBC{x$_uk@Nj~%4mjgMj|g*OgX2^S{;~jgWvJBvSGLn;(hhs)HDb=30V?M6%itkw^{?#7H!^ zaS)M6eh5S)l5YbMiR6bsL?Zb%5RpiJ2o4JpDIEBdE(b&;k|~FX zl9fGxh(z)P@bx0md}%{OB6$}Okx2UzL?n{ogNQ`3?+}qlrW_&?$-97vL^98Sa)zDk^B&dk;wBCQ*L-RIFU#`1H?$=35F>* zVjFQoB%0d}h?#YBPZc5($-YC(7uo`lPlOVsRpo4If3;aH^jHxH1|X#kNQ! z-v%NQ*}?|%%HVf!GDf!AfK@=$1mn6jvTMb0EARYLi2@?^NaW6AwG9{tClcu(03s6E zW8v}$oYp6%+<Po~ zA((QmulPeqWLwP5M>sX-xrzv<6@n=@avkXqB(l%IbqI(aO{_L|L)9g$wsF~Llg`^Y z;f@hRON7-nR2yZ5>AXLL)#hfDzK+$tv=7F05;(n%u-e9@<3kLGy^FwP8P^U@wlxI~ z5Ru5nlxsHp+?~g2U)r|`ZWg!OBoS8I2ytYmkVvQh5Ru64RxqrZgE`=qV-7t zZd5ux#2DFU;I0}(S;OFIamQI>gnc)<8hJq^QtAUD64?t1!WQ>V-6j$#d%(|;$c{wd zwTvVOClWbA;dUcL?=~2HLu--0WCyd^4YHP@<=|u!u+Tmci`!dA47z;uZGYFlTVmd3zT@)-wDWoOIrvKybCz_AUae zWvn>z)^y(9#R~gw{5Uun4rdPno`t3)J67AUVC2H-lI_t718ul6IO&qZ>fmM>C=5=z zWD6U7EQ6@Qi9YSd0B-IE6qW+xK8+88Qk^B(jxRVW8Kx?}5`Y z9v454MA{iZ34v3-cd)b!G{(=7NC*9#mLQQ61>mPZv_de@20G*Cbl!pO3R}Fkkpd-! zuY1~Hiw#^xn{?iGGYDD+KI2p;6U;-5Ee5ql1BWd(wirLpaLB@fmcvZ0pVLpLKEMou zXo)bUh85$Wi7we11|iFUUU1SSdlxJ0rs2HcM4yh|0ZoEviLjf-mEh+rSQ``&llYM5 zJQ1{kytwPK;^&@?Ri0C}D6Sk!>+*gD7hl#4If0 zyq^KgGJ+L{mUP~Ug1}`NEelRM?`W3^3sEaB2wDcZ;^%bUsgK}i8T^VnP7H^wcF?n! z_mT(;YqT(ajzso9*^|zVL_lWq2Prk;o=8$Xf>9;uahdIZc5X=jUEWSZ$+N z@pB|{1Rc;V48JBVR@h} zWr;~xZ3HQPjzkWD1JGpzDmanI4o~2@fWFm-@B|EjMS%tqIno~}T(&X= zV#@Fy#in;pgeRWyflhe33*LXrub@bNcCxdVpv-M@`-WPVFHB zLd!8M$qdBQo;(1wY$gVNmiOcVpJmfC(6byc@-hHjlI#Of%K;+^Cmsya+9bCGQR`^H zX*r)v8VOE~<^a>O=^=>)r}iasU=Xdk98BBv40tVXm82v=xzYSQfNQx;Y%!_x`M8s4 zglO5Z#h_Y+^LO{}e{%cm(esD@^An6_CQbf&@7~4ZC(j-|dG`BPcmCI_61sVegpdu>5RV&h5hd0m;dqN_TuN)zrTGoYa(p3 zCU$RHIIQopF@w$ytqsx64knCmMZaf<4fyO3IsT3>yu76&e0L1#`#zga%|3g1{OsuM z*+vnP)}|McIk9xNWb_~P~t zPyXr8FK>VG=YRg?&7c2xvw!sI-{1eiy>IS*^Yq12T08sZ=~vHQ-TmhCPp_GAw|Dt_ z$QPfU4VKq`{QT1&){5{g*={Z`%3t_SMbHCof(#qzVo#i<{?nDlP;BmRLOtxx_4g+6%j z?caL(^yDue-MszTi?3gPH8k<)=Hm9N+ow#-SA21K@m2xIcaKlq{etm-efuTVacNdR$*Nf}@Y4_31-N(;gKD~Z@|C+IVa&w)f73uC>y!)pk z|GkSWxycedtnWc(fwQ?>yxm>KKfPU%|5<-|C&+)+7ijmdANfwo{j0kEs;=*(f$zlp z*V*+~b$urdd?)6=&aUrGU6c5PkoNOW|3vhW;Px24ybE&^4!?=6;@RSV#A*BCmv`gc zQX@^x6Xlt^U!PwL&-eMuA5PuY-+tI{{q0G|^|$T0!uaj3>-hy9r+df6mf@BD?PBq_ z=NE4r#vjfc#`AY^>^CoOAAjHR(8%(V z(8!;+G-@4FGcu!bX)H&HqK$$m({h|8+JK0f(YPR+0D4a2Mz{JxCX}OrIUnibkszJ^ zmOTByXPVO}b5x)CzyQaa@o@*te4KlXd)HGwjy)(7ocD!%{y3eU@qy=%Gda;H*J_&O zrFY}ik=bv72u%7^v~huQN@Ik^&Hp)#no{+dblJ##if@#;&uC=Zb3`?xaknekra29@ zsDIRFj+5&dA8-jNn4QxoDUq%y^yP`)IUnWW11@FyTMEHzJfMwp@EISIBk3T~M!}G1 zqo`H1f&Vn4kq=Koc}C-=W%7!m)!O3r&L~}-@qt2-lSI+Rg?Q7FF`v@7e>ZNmh&JH9 zL>uUna~gLXrDrZUjx_L$kHgPo(PlJGN^>Q|G>KimyG-{EH#$`0E z1yBcT{bJ6?y`0&1!TGQq3{qW=R_A;yEzdP9nQbjj#JHa||1Gw$+T#+0#}_oB9IEQK z7i> znZjcUVq)r?)E-qlreTh%J?voVnH^C3B!FL|?tcCal;!mXR#&YLG;o5id^jMu#Bg(FV+bXeZ_*&|Rg!0K!=Jx&3b%S17$!0cx{P z%@+m`%)BqD*sJ!+9|s$TXi0ovfaL&m)*hOtLFwAe(ggH zZ|&oGRo=RSR{J05j*e#n=VcoTZJ<=m`%D48*8*5xHBXspj-x=)8C7`m_9%R+_NdSD z_yW#V^BJ?15<0a9+CRZ@TGL=w)EtTf<9P*ANsTYaEj6D(vZ=8IfvDRX zSebJ<0L>~sP}QnEB8%o5_nzkMp@P~Y!0s%0u{|XRLtftnEwR4KhR}TN6XK!gPTIVG zAV7C}1DIKSqyAz};}&SmA?`$!yi^^Qyo87)FWYnV4@{HlA7CBki(70yunbDxKm;`3 zfLoZ!#!YYMOZe!3r4=7HtfW)aQa%mlGKCiN-{LZOEpT1v<(3FleM|EE};wjX8U9@qvX|d;o@) zUcgGNu_U)tV+rzXjV18r{f)}afr8X_3uvSA%>XgVeVO@KV)*MDq?N1BM0GVr036mH zMsI2#3X+1q%Z5-orJTRM0jyc|B@?yUtK3q6i+Ycxd!=XI@hTkva3nsqb`tLM??Nm8 z1sWN#;v09+r@D`+$Xz(mDrSNY<(rSA3F(ClW5s#U#_h@ZH<%il2k=!61=>Iu)o%w% zyJ)pOFnP5;Vg{WXfmZVm+JKjve}gM3rF+VKwB9hQJD+;C3qRhE};bXaikZ->tKv!1ve&0DuFEjCDmW zsQQ8ps5uD|QPT!^!n`l!?@I?cC8+NXjBfpQJi#H_cp7a^V+$)ez#`P1gL_pzAv7LU zbzcDVtUiNKs=bci4kUl|g`2Bx4@BQ;4=m)`H^?oOUU1QyZ-92rze|Fs`A+O>Ox@}W zzI?4Mpsq`&fJN8Z!kky1$(B}M*mjGL)n9x#l+8D=T;}rP)YSNb*jTy;-mu1(hxBSJ zf!K3jm{s<<;%3*lu|3zgfqzrumh(%?Ml@ra9Gn~bT)6TC0-9HNvCjLzH?G9abVV58 zoCkcp1}VO;apMy;Zh3yabcKKK@gRLwdkI_?ES8wlcaIXJ@bSR$@{u7Jom zj)yj|66Wo3jlSD!o6PY{%fWtMzvc3W=T$;0uPsieThG{l8eh(+`Wpk&el7?2T*Y@{ zZ|8Kz`H0}Q)ZUph*KTiM7tg=Tu+^9Yr&)8HTubSNTuaHz>1=(Mt*-gX{{uv2y#6xp zAK`Sh$M9Brz}kD?06@h)fACX$ZVGK6InKXJ`mev+wu0r>^5V-^|B}e`+6Pa+`6}NO z+!MzJ(AqyBvML{#3{UPf&t=1xukRA-R{wakviW*1#_~A+%@>@1Nd)2i3$$@Be%3$k z)R)hNr(F9L7qfj9NPFY?4z)L)E1S~@lRaOkXDS=YtO_)kemg)ZMXS6I5GC#VP%BjH zjcik`w-gn5+yEV^^~RQ6z6w`J%U9vDXzQMP^Z^15I86h{Y_1n> zfO=jLbvwVoZ|nSsG}5B{h=^NyA+O?j$_?b&#}m3V-@wP8_ZcL-8gsDuN(bc3OSV3n z<$l??dpG|E{CHD@ zH_&gZE{$)rO+f=a$9dhP#)vdwjR%z@_JOI+DZh@4VEJ`mB9vbT_Cl`(w)>Ko1Fq5w z58yRl)x(k69Is%^b;Sv0$w5hi{S8j!YA+@_?>R}?NUab2?3%kI-I{N_D>m;RNg4AI zvin?@uZ}zav){6_mtTx$TYhoM(mdwuF69>khf#B!Iw;q)k(H`5W@rO9V%|U0SKnP$ zUXR~a%?`9W1BW)A=bnFq@-?qP3O8$vQn=|k1b~n8ok6ScnJct`y07n!m!L#zdqibu ztpzYC%0HkIr($u+b87xUsyz`riXLvZ0)``3wkWcf3F|?;l|BB^!YIB^$3NG~d9< znYYJ78YLUgg?Nv}beH`AyP@_ChO+iuvY55+rY5!YoXS4g9uOL8-vwx{_FXDcD-Xh{ zbNMe!tFkFz=~W&C)V#`rP}Ns)9-(B#(_k=^e@ba%`7eMil&uA8p?pHBLCVGhN!WV{ zkHFWMlin>o^YlXLnPUj^F*9o1fPt)W;~1>Q4KRfoH^S+f_ndZ@{&4jwUq>`uaW^G* zwKuUH)LI~$Q)_{!qV_97`_dm62xTupJE(b&D_Z*%<%tz{Q!ZbA9i<=T|B+S>u*ht! zQa$Oj6N*`@mNVA_%1`8kuVQBaZ(DySd~{su@;C5uYW^kV;rU0kO3gpOd&`zFgM6Nh z6E+@)n(Kh0!2ZT~Pgi{HPl97yHUPY2*9mfcVIZ8(+XEn>zKg43pMg@Go_{=@;`Npb z2ln-_P!-#AL{M=G8MoStQA@>icvoeAi6F|)A@f>!IK0HNp&U*0n(o>ZJk0UD(p-NW z-P!j6w7vFIkk~8U8W$|Q7N~cu^?{kLZ%{5@`x;epwwGYV_ZZ=4*BAwt*?mdWRJ4Io zI@bZ=R`rFjvHHT{cFh;kIZYcccfbiv1YzvI}@pwJvePYRoBLt1+j#srE^#ugV^! zoZ9n`Rax;Hp?%qNGDbD8f{IY>QQPSGm+i`Ph?hkwKElPU93z>aiY0-tsJ)oSQ);g9 z%1ZfCygE~Jmr|0}0lv4_2d9YTTaezU*nq9L&N*?FD<{Y*DqkvBjl8z7D76n!@!4~T zw~)M-kZS4vQ6^L4MoCfADB$(H=h3yA_oRILw{_2pDz`pk0Ys?Bh%?QaFR;}fapL@v z2bp?|PMlwIy4v&Q#Q7yBXys>PLVLY+{R@Hp0DzqD8KoL$)VQ&?*ZO5|?{AE!z~{12pJ>^5Y^~N7pNq>yz^Fm4zI+W z;H!HWlx|gBZpyi8O;f2>YavJZUV|JJ^>;a3w61WGO3&;Xu0 zWbJ>Xaw{fg#4DG3>H^WbaQC~jJo{YVO>`ixSm&wQl$+J9yz>2brquk}XldF>^< zg=pZTDSg4%zIvu#w_2PrPcc5dXMJ|8P)PtwkPUU$Wqsy z$S-S8%M|TV9VXKCY&Doo{(Wx%tMMSTozrR@dXk?jW4;D`UcmI>l?d1yCZ{Ku@DhcuPx3wOZS{}dha9^R52Z0 z?!M$1J=qUtLFFi*m2bf{`qneoAWH{Kp&E}9dpigpy*H6|w4TWl)?DM46$j*6me(8M zQQ1|rS8IWxtTn@Fa>XQMxJy@5VAR~8`n3FZyu>>93)q3@3z?Q0x7>3r*~sU3Zg9`_ z1Yi5q!DjIs$Gfj{5-Q$n|Kpx(<*AwWWy?4Ms`1@X7FqIALfW(weWp~r>wR+^nj-iDh1SLNZmYQx4!tUao#spNS!Aj4+K}Z|t1q)1)-H z+B

fu^t9TQ=OLbzy6<5fT}?<~Uo@)}Jxfjxu-D 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≫(sL5EwoiN)`lS0-bJtB!W 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